Re: Hiding the effect of concurrent finalization

"Boehm, Hans" <[email protected]> Thu, 11 Feb 2010 18:39:56 +0000
Newsgroups gmane.comp.programming.garbage-collection.general
Message-ID <238A96A773B3934685A7269CC8A8D042578414CEFC@GVW0436EXB.americas.hpqcorp.net>
> From: Florian Weimer
>=20
> I've recently come across a rather puzzling problem and I=20
> wonder if it has been discussed before.  Suppose you have got=20
> a language which sports garbage collection, scope-based=20
> automatic resource management (like the WITH- pattern in=20
> Common Lisp, or C#'s "using" construct), and coroutines=20
> (user-scheduled threads, also called one-shot continuations,=20
> I believe), but not (explicit) user-defined finalizers.
> Unfinished Coroutines are not automatically part of the root=20
> set (this is different from Java threads, for instance.)
>=20
> The problem I have is what happens if a coroutine object is=20
> garbage-collected, but there are still stack frames on it,=20
> including some which involve automatic resource management. =20
> Presumably, the associated cleanup code needs to be executed=20
> when the coroutine object becomes unreachable.  But this=20
> means that we now have a generic, user-defined finalizer=20
> facility.  And this seems to be unavoidable.
>=20
> Consequently, I wonder if there are any good ways of hiding=20
> the concurrent nature of finalization.  One idea that comes=20
> to my mind is to run finalizers for objects of a specific=20
> type only when new objects of that type are created.  Are=20
> there any better ideas?
The standard solution for single-thread environments seems to be to put rea=
dy-to-be-run finalizers into a queue, and then require the user to explicit=
ly take some action to run those, ideally when nothing else is going on, an=
d none of the data structures updated by finalizers are currently being upd=
ated by the mainline code.  Java.lang.ref takes a similar approach, even in=
 a multithreaded context.

My (unproven) intuition is that running finalizers for T when a T is being =
allocated is relatively likely to run finalizers when the underlying data s=
tructures are already in use, and thus perhaps more likely to break things =
than running them in response to a random allocation.  I wouldn't recommend=
 either.  (We currently do the latter by default, for historical reasons, a=
nd it works in the simplest cases, but I still wouldn't recommend it.)

Is it possible to run into the same kind of premature finalization issues d=
escribed in my 2003 POPL paper?  I think that restricting yourself to a sin=
gle thread makes this less likely, but not impossible.  That might be an ev=
en scarier problem, in that it's probably very difficult to provoke in prac=
tice in this context, but handling it cleanly may require prohibiting dead =
pointer variable elimination in the compiler.

Hans

>=20
> (The Scheme approach involving callbacks for entering and=20
> exiting the protected scope does not seem to reflect reality=20
> that well; it is not always possible to gain access to the=20
> same resource after releasing it.  For instance, a file might=20
> have been deleted in the meantime.)
> =