On Tue, Jan 19, 2010 at 11:00 AM, Alexander Larsson <al...@redhat.com>wrote:

> On Mon, 2010-01-18 at 11:25 -0500, Adam Plumb wrote:
> > hi all, I'm working on tracking down the root cause of a segfault in
> > nautilus/nautilus-python/pygobject that is actually quite easily
> > reproducible.  I'm the maintainer for nautilus-python and have been
> > working all weekend trying to figure this out and find a way to fix
> > it.
> >
> > To reproduce, install nautilus-python, then install this python script
> > in your ~/.nautilus/python-extensions folder:
> >
> > import nautilus
> > class Test(nautilus.MenuProvider):
> >     def __init__(self):
> >         print "Init Test Plugin"
> >         pass
> >     def get_background_items(self, window, folder):
> >         return []
> >
> >
> > Then from the command line kill nautilus (nautilus -q) and run without
> > a desktop (nautilus --no-desktop).  Make sure the python plugin has
> > been loaded, then navigate to any XDG folder (Documents, Downloads,
> > Music, Pictures, etc).  Then quit out of nautilus.  You will always
> > see a segfault with the following trace:
> >
> > (gdb) bt
> > #0  PyThreadState_New (interp=0x0) at ../Python/pystate.c:201
> > #1  0x00007fffeb7eb90c in PyGILState_Ensure ()
> > at ../Python/pystate.c:581
> > #2  0x00007fffeab96a10 in ?? ()
> > from /usr/lib/pymodules/python2.6/gtk-2.0/gobject/_gobject.so
> > #3  0x00007ffff382f232 in g_datalist_clear ()
> > from /lib/libglib-2.0.so.0
> > #4  0x00007ffff3f2052f in g_object_unref ()
> > from /usr/lib/libgobject-2.0.so.0
> > #5  0x00000000004ca231 in free_xdg_dir_cache () at
> > nautilus-file-utilities.c:344
> > #6  0x00000000004ca2d7 in destroy_xdg_dir_cache () at
> > nautilus-file-utilities.c:357
> > #7  0x000000000051f448 in eel_debug_shut_down () at eel-debug.c:109
> > #8  0x0000000000444694 in main (argc=1, argv=0x7fffffffe368) at
> > nautilus-main.c:554
> >
> >
> > Here is what is happening.  When you navigate to an XDG folder,
> > get_background_items is called on the folder (this gets a list of menu
> > items for the context menu) and a new pygobject is created for the
> > folder (to pass from nautilus-python to the plugin script).  When
> > nautilus is shut down, it calls nautilus-python's
> > nautilus_module_shutdown() function, which in turn finalizes its
> > python intepreter (with Py_Finalize()).  However, after module is shut
> > down, nautilus tries to free its XDG dir cache, which contains some
> > sort of pygobject data, because line #2 of the bt is a call to
> > pygobject_data_free, which makes a call to pyglib_gil_state_ensure()
> > before it can free its data.  Hence the segfault on the NULL interp
> > object (Which has already been finalized)
> >
> > So those are the bare facts.  The part that I'm stuck on is why the
> > XDG folders' NautilusFile object is hanging on to a PyGObject object
> > (from get_background_items) when it should have been freed earlier,
> > either at the end of the get_background_items call or during
> > Py_Finalize().
>
> It seems that something did a g_object_set_data() on the NautilusFile
> object, attaching some python object, passing in a destroy notifier that
> probably unrefs the python object which is called when the NautilusFile
> is freed. However, this then gets called after python is un-initialized
> because the user data was not unset.
>
> You need to figure out first what is setting this user data, and
> secondly why its not cleared before finalizing python.
>

I mistakenly sent my response directly back to Alex, here it is for the
mailing list.

The user data is getting set by pygobject when the get_background_items
function converts the NautilusFileInfo object to a pygobject (with
pygobject_new).  When a PyGObject is created, it in turn calls
g_object_set_qdata_full(), which in turn calls
g_datalist_id_set_data_full(), which in turn calls g_data_set_internal(),
which I'm guessing is what is attaching the user data.

I think the reason why the objects are not getting freed is that the
NautilusFile objects that are XDG folders are getting cached somehow, and
the objects don't get freed until nautilus is shutdown (after
nautilus-python, and the python interpreter, gets shut down).

I'm thinking I may have to track these NautilusFile objects and free that
data manually before shutting down the python interpreter.  I will try that
and see how it works.

.... here is my second response five minutes later....

Sweet!

That was exactly it.  I was able to set the pygobject instance data to NULL
directly after making the call to the python plugin in
get_background_items.  The exact call I made was:

g_object_set_data(file, "PyGObject::instance-data", NULL);

This got rid of the segmentation fault, since the instance data was no
longer being held until the very end in the XDG folder objects.

Adam
-- 
nautilus-list mailing list
nautilus-list@gnome.org
http://mail.gnome.org/mailman/listinfo/nautilus-list

Reply via email to