I've got a problem with finalisation.
The picture is that I have an object representing an external resource (various structures allocated in an external library). That object can clean itself up by finalisation if necessary. When it is cleaned up (whether by finalisation or not) it issues various API calls, and they, in turn can result in the external library invoking various ExternalCallbacks associated with the object. That all works fine when the object is cleared normally, but when it is cleared by finalisation, I'm getting walkbacks from the finalisation thread. The problem is that, although the object in question is still holding on to its own references to the ExternalCallbacks (so they haven't been GCed), it appears that the corresponding entries /have/ been removed from the ExternalCallbacks class's registry. In the debugger, I can see that the ExternalCallbacks instances still exist, and that their #thunk-s are normal (so they haven't been #free-ed), but the registry contains the DeadObject at the index corresponding to their cookies. I speculate that objects can be removed from weak collections (such as the registry of ExternalCallbacks) while they are still reachable from objects on the finalisation queue. If that is the case then is it a bug ? And anyway, how do I fix or work around it ? -- chris |
I wrote:
> I speculate that objects can be removed from weak collections (such as the > registry of ExternalCallbacks) while they are still reachable from > objects on the finalisation queue. If that is the case then is it a bug > ? And anyway, how do I fix or work around it ? I'm sorry to nag, but I'd very much appreciate an answer to this. As it stands it appears impossible to clean up objects with finalisation if they use callbacks. If that's the case then OK, fair enough, my object will not be finalisable, but I don't want to go that route unless I have to. TIA -- chris |
Chris,
> > I speculate that objects can be removed from weak collections (such > > as the registry of ExternalCallbacks) while they are still > > reachable from objects on the finalisation queue. If that is the > > case then is it a bug ? And anyway, how do I fix or work around it > > ? This is effectively issue #1580, which is recorded as follows: --- The garbage collectors scan to mark finalizable free objects is currently combined with the weak reference "nilling" scan. This means that it is possible that a finalizable object may be marked after any weak references to its children have already been nilled (it is correct that weak references to the object itself should be nilled, since when an object is finalized there should be no references to it at all apart from the finalization queue reference). An example is the ExternalCallback objects. These have a weak register mapping integer indices to objects. The integer indices are saved in the thunks, and are passed back into the image when the callback occurs. The index is then used to look up the relevant callback object in order to invoke it to handle the callback. Consider a situation where a callback is owned by some object, and is passed to, and capture by, some external API. The owning object uses finalization to inform the external API that the callback is no longer valid. This means that the callback must remain valid until the finalization is actioned. In order for the callback to remain valid, the weak registry must retain the reference to the callback object. Because of this bug, it is possible that the weak registry will be encountered in the GC scan before the callback owner. If the callback owner is no longer referenced, then the callback itself will be unmarked. Thus the scan will nill out the weak reference. Later in the scan the finalizable callback owner is encountered, and its children are recursively marked in order to rescue them for finalization. Thus it is possible to hit finalization with an invalid callback. This problem was encountered in practice when implementing the FileSystemWatcher class which registers a BlockCallback as the APC callback function for overlapped I/O. In order to complete finalization the directory handle is closed, and the ReadDirectoryChangesW sends a further APC. This APC cannot be processed because the callback is no longer in the callback registry. This causes either a walkback (due to the use of the invalid callback index), or a GPF. --- The problem has been addressed in Dolphin 6. Best regards Andy Bower Dolphin Support www.object-arts.com |
Andy,
> This is effectively issue #1580, which is recorded as follows: > [...] > The problem has been addressed in Dolphin 6. Great. Thank you. -- chris |
Free forum by Nabble | Edit this page |