------- Comment #20 from daney at gcc dot gnu dot org  2008-09-26 15:58 -------

1) Create an object.

2) Enter a synchronized block on the object and do Object.wait().

3) In a second thread, enter a synchronized block on the object.  There is lock
contention, heavy lock escalation is guaranteed.  Hash synchronization code
registers a finalizer recording the old finalizer.  The old finalizer is null
as no finzlizers have been registered for the object.

4) Create a WeakReference to the Object.  This adds a finalizer, overwriting
and thus losing the Hash synchronization's finalizer.

5) Both threads leave the synchronized block.  At this point the heavy_lock
object in the hash synchronization code in no longer in use and is eligible for
clean up.

6) Many other locks are acquired and released, some of these hash to the same
value as the lock used in steps 1 and 2.  Eventually the hash row for these
locks is cleaned up.  The clean up code restores the saved finalizer from step
3 which was null, thus overwriting the WeakReference's finalizer.

7) WeakReference's referent is GCed, but its finalizer has been removed in step
6, so it does not get cleaned up.

If you ever synchronize o the If the object itself is a WeakReference, the same
thing happens, but ref->enqueue is called on the WeakReference.  If A different
type of object has been allocated in the WeakReference's previous location,
when  the referent is finalized ref->enqueue will be called through the vtable
of the new object resulting sometimes in SIGSEGV or other types of bad
behavior.  


-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=18266

Reply via email to