Re: Tracking down and fixing a segfault in nautilus-python



On Tue, Jan 19, 2010 at 11:00 AM, Alexander Larsson <alexl 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]