GNOME Bugzilla – Bug 334039
garbage collection of org.gnu.glib.Timer causes application to abort
Last modified: 2006-03-10 16:25:43 UTC
Please describe the problem: looking at org_gnu_glib_Timer.c it looks like there is a double free occuring since clean up gets called twice. Once when the timer fire function returns false (do not continue firing), and again when the timer is getting finalized, and calling stop(). Steps to reproduce: 1. 2. 3. Actual results: Expected results: Does this happen every time? Other information:
Created attachment 60985 [details] [review] this patch checks of the handle has been freed already if not it frees it
+1
Created attachment 61001 [details] [review] fixed previous patch... this one retrieves the value of the field instead of checking the fid
Comment on attachment 61001 [details] [review] fixed previous patch... this one retrieves the value of the field instead of checking the fid >Index: src/jni/org_gnu_glib_Timer.c >=================================================================== >RCS file: /cvs/gnome/libgtk-java/src/jni/org_gnu_glib_Timer.c,v >retrieving revision 1.9 >diff -u -r1.9 org_gnu_glib_Timer.c >--- src/jni/org_gnu_glib_Timer.c 28 Feb 2006 02:43:32 -0000 1.9 >+++ src/jni/org_gnu_glib_Timer.c 9 Mar 2006 20:35:59 -0000 >@@ -22,10 +22,15 @@ > // reset handle field > jclass cls = (*env)->GetObjectClass(env, obj); > jfieldID fid = (*env)->GetFieldID(env, cls, "handle", "I"); >- (*env)->SetIntField(env, obj, fid, (jint)-1); > >- // delete back pointer >- (*env)->DeleteGlobalRef(env, obj); >+ //check of the pointer has already been freed >+ jint handleValue = (*env)->GetIntField(env, obj, fid); >+ if(handleValue != -1){ >+ (*env)->SetIntField(env, obj, fid, (jint)-1); >+ >+ // delete back pointer >+ (*env)->DeleteGlobalRef(env, obj); >+ } > } > > static gboolean fire_method_invoker(gpointer data)
So your patch makes sense, but now that I've looked at this code for a while I'm not entirely sure that this *class* makes sense. How come we delete the global reference for Timer when stop is called (which may or may not be called because of finalize) if the thing that happens after finalize is that the instance is going to be garbage collected? Put a different way, I would have thought we either would have had *tons* of calls to DeleteGlobalRef in our JNI layer ... or none. What makes Timer special? The fact that glib can terminate the timer, and we might somehow not know about it? AfC
Timer is special because we create a GlobalRef to it from JNI. If you create a GlobalRef, you need to remove it, otherwise it's a leak. From what I can see, the object will never be finalized before the global ref is deleted.
*** This bug has been marked as a duplicate of 331052 ***