Re: GSource finalization lock (Re: [Bug 459555] gdk_threads_add_* docs question)

On 8/22/07, Tim Janik <timj imendio com> wrote:
> On Wed, 22 Aug 2007, gtk+ ( wrote:
> > unfortunately the glib main loop mechanism allows sources to be destroyed
> > during dispatching (e.g. when a timeout/idler is removed while the gdk lock
> > is
> > being held) and also after all GSources have been dispatched (e.g. due to a
> > reference count which was held across dispatch()). so whether the gdk lock is
> > being held during destroy is unpredictable.
> hi Owen.
> while writing this comment i had some more thoughts on attempting to
> fix the unpredictable lock issue with main loops. do you see compelling
> reason to not implement the following?
> we defer this code snippet from g_source_unref_internal:
>        if (source->source_funcs->finalize)
>          source->source_funcs->finalize (source);
>        g_slist_free (source->poll_fds);
>        source->poll_fds = NULL;
>        g_free (source);
> for later invocation by keeping a list of need-to-finalize sources
> on GMainContext.
> this list is to be processed:
> - immediately by g_source_destroy if this context is not currently
>    in prepare/check/dispatch, i.e. when g_main_current_source()==NULL
> - directly after the toplevel source->dispatch() returns, i.e.
>    when done dispatching && g_main_depth() == 0.
> the above is basically applying the example free_allocated_memory()
> technique from the g_main_depth() docs to our GSource finalization problem.
> with this we can finally document that there's never any main loop lock
> being held (or custom dispatch lock like the one from gdk) during
> GSource finallization. however, we will temporarily starve and stack-up
> GSource finalizers during recursive main loops.
> the question is prolly whether the starving during recursive main loops
> can be considered minor enough...

I'd certainly consider it legitimate to both:

 A) Run a recursive loop for an indefinite amount of time (if nothing
else, you pop up a modal dialog with gtk_dialog_run(), the user is
away from their computer for a day, they come back)

 B) Have sources that allocate significant amounts of memory (every
minute, you poll some website from a timeout, temporarily creating an
object with a buffer that you fill in asynchronously from a GIOChannel
as the data arrives. The IO source's destroy notify unrefs the

The combination of these two legitimate things could give you
essentially unlimited amounts of leaked memory.

I think the situation is pretty much like in a garbage collected
language; you should be doing almost nothing in your finalization
routine other than freeing memory, because finalizers get called at
unexpected times, from unexpected threads, etc.

Directions to solving the underlying problems:

 - We could just go ahead and make the GDK lock recursive; while
making it recursive turns obvious problems into subtle deadlocks, it
doesn't break any code that would otherwise work.
 - Work on making Pango threadsafe. Work on making GDK partially
thread-safe. (It would, be possible, for example, to allow freeing GDK
resources from any thread.)

- Owen

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