I have a case in which I want to register objects for finalization
in order to ensure that external references (file handles on OS pipes) are closed if the object has not been properly closed by its user. I thought it would be a good idea to unregister these objects explicitly when I know that they *have* been properly closed. This seemed like a good idea because allowing weak registries to grow can be a big performance problem, and I thought it would be good to keep the registry as small as possible. The result appears to be an occasional race condition in which the finalization process attempts to remove an element that somebody else (me) has removed from another process. At least I think that's what's happening, see attached png of the debugger. Is explicitly removing an object from the finalization registry a Bad Thing To Do? Or is this perhaps a bug that should be resolved by synchronizing access to the finalization registry, or by ignoring the error condition in the finalization process? Thanks, Dave FinalizationRaceCondition.png (26K) Download Attachment |
David T. Lewis wrote:
>I have a case in which I want to register objects for finalization >in order to ensure that external references (file handles on OS pipes) >are closed if the object has not been properly closed by its user. >I thought it would be a good idea to unregister these objects explicitly >when I know that they *have* been properly closed. This seemed >like a good idea because allowing weak registries to grow can be a >big performance problem, and I thought it would be good to keep >the registry as small as possible. > >The result appears to be an occasional race condition in which the >finalization process attempts to remove an element that somebody else >(me) has removed from another process. At least I think that's what's >happening, see attached png of the debugger. > >Is explicitly removing an object from the finalization registry a >Bad Thing To Do? Or is this perhaps a bug that should be resolved >by synchronizing access to the finalization registry, or by ignoring >the error condition in the finalization process? > >Thanks, > >Dave > > > exactly the pattern you describe: unregister method removes the file stream from the registry via remove:ifAbsent: close sends unregister It seems odd that your race condition occurs but I've never had such a problem with file streams. Further investigation shows that Socket does the same thing. Maybe you could look at them and see where your usage differs. Is the problem Squeak version dependent? I've looked over WeakRegistry in 3.7 and it looks solid. No obvious race conditions...but they are never obvious, are they ;-) David |
I'll also note MPEGFile uses the same pattern which was copied from
the Socket code originally. This pattern of code is used in other class I've written, (6 more in Sophie) and if someone can find a bug in it this pattern of code would be interesting to know. I'll note if your code does cleanup processing as part of an explicit method send, then in the finalize method you may need a guard clause to prevent double usage of destroy logic (which might cause problem). On 14-Jun-06, at 10:13 AM, David Shaffer wrote: > Did you ever sort this out Dave? Looking at StandardFileStream I see > exactly the pattern you describe: > > unregister method removes the file stream from the registry via > remove:ifAbsent: > > close sends unregister > > It seems odd that your race condition occurs but I've never had such a > problem with file streams. Further investigation shows that Socket > does > the same thing. Maybe you could look at them and see where your usage > differs. Is the problem Squeak version dependent? I've looked over > WeakRegistry in 3.7 and it looks solid. No obvious race > conditions...but they are never obvious, are they ;-) > > David > > -- ======================================================================== === John M. McIntosh <[hidden email]> 1-800-477-2659 Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com ======================================================================== === |
John, David,
Thanks for your replies. No, I did not really sort out the problem, I simply quit unregistering the objects, which of course made the symptoms go away. I suspect that I was registering and unregistering things at a higher rate than would typically be the case for file streams and sockets, so perhaps that increases the likelihood of the problem. I'll take another look at the socket and file stream examples and see if I can spot where I went wrong. By the way, I did try synchronizing access to the registry, which indeed made the race condition go away. But some other horrible problem cropped up, at which point I decided I was wasting my time trying to violate the laws of nature. I'll have another look and see if I can clarify what was happening. On Wed, Jun 14, 2006 at 10:39:51AM -0700, John M McIntosh wrote: > I'll also note MPEGFile uses the same pattern which was copied from > the Socket code originally. > This pattern of code is used in other class I've written, (6 more in > Sophie) and if someone can find a bug in > it this pattern of code would be interesting to know. > > I'll note if your code does cleanup processing as part of an explicit > method send, then in the finalize > method you may need a guard clause to prevent double usage of destroy > logic (which might cause problem). > > > > On 14-Jun-06, at 10:13 AM, David Shaffer wrote: > > >Did you ever sort this out Dave? Looking at StandardFileStream I see > >exactly the pattern you describe: > > > >unregister method removes the file stream from the registry via > >remove:ifAbsent: > > > >close sends unregister > > > >It seems odd that your race condition occurs but I've never had such a > >problem with file streams. Further investigation shows that Socket > >does > >the same thing. Maybe you could look at them and see where your usage > >differs. Is the problem Squeak version dependent? I've looked over > >WeakRegistry in 3.7 and it looks solid. No obvious race > >conditions...but they are never obvious, are they ;-) > > > >David > > |
This is just to follow up on my original question.
I tried to reproduce my problem in a stand-alone test. I was not able to produce any kind of concurrency problems when registering and unregistering objects for finalization, regardless of how many processes were doing the register/unregister operations. So yes, it is perfectly OK to explicitly unregister objects from a finalization registry. Thanks, Dave On Wed, Jun 14, 2006 at 09:42:41PM -0400, David T. Lewis wrote: > John, David, > > Thanks for your replies. > > No, I did not really sort out the problem, I simply quit unregistering > the objects, which of course made the symptoms go away. I suspect that > I was registering and unregistering things at a higher rate than would > typically be the case for file streams and sockets, so perhaps that > increases the likelihood of the problem. > > I'll take another look at the socket and file stream examples and > see if I can spot where I went wrong. > > By the way, I did try synchronizing access to the registry, which > indeed made the race condition go away. But some other horrible > problem cropped up, at which point I decided I was wasting my time > trying to violate the laws of nature. I'll have another look and > see if I can clarify what was happening. > > On Wed, Jun 14, 2006 at 10:39:51AM -0700, John M McIntosh wrote: > > I'll also note MPEGFile uses the same pattern which was copied from > > the Socket code originally. > > This pattern of code is used in other class I've written, (6 more in > > Sophie) and if someone can find a bug in > > it this pattern of code would be interesting to know. > > > > I'll note if your code does cleanup processing as part of an explicit > > method send, then in the finalize > > method you may need a guard clause to prevent double usage of destroy > > logic (which might cause problem). > > > > > > > > On 14-Jun-06, at 10:13 AM, David Shaffer wrote: > > > > >Did you ever sort this out Dave? Looking at StandardFileStream I see > > >exactly the pattern you describe: > > > > > >unregister method removes the file stream from the registry via > > >remove:ifAbsent: > > > > > >close sends unregister > > > > > >It seems odd that your race condition occurs but I've never had such a > > >problem with file streams. Further investigation shows that Socket > > >does > > >the same thing. Maybe you could look at them and see where your usage > > >differs. Is the problem Squeak version dependent? I've looked over > > >WeakRegistry in 3.7 and it looks solid. No obvious race > > >conditions...but they are never obvious, are they ;-) > > > > > >David > > > |
Free forum by Nabble | Edit this page |