Re: glib: processing events in multiple threads

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

 



On Tue, 2013-04-30 at 10:42 +0200, Patrick Ohly wrote:
> A quick and dirty workaround would be to ensure that at regular
> intervals a "watch dog" timer wakes up whatever thread currently owns
> the main context. But what's the right solution?
> 
> I thought that g_main_loop_run() with separate GMainLoop instances each
> time a threads needs to wait might work, but I can see at least one race
> condition with that. The code would look like this, for the simple "time
> out after certain time" case:
> 
>     gboolean timed_out(gpointer data) {
>             GMainLoop *loop = (GMainLoop *)data;
>             g_main_loop_quit(loop);
>             return G_SOURCE_REMOVE;
>         }
> 
>     ....
>         GMainLoop *loop = g_main_loop_new(NULL, TRUE /* running */);
>         g_timeout_add(1 /*ms*/, timed_out, loop);
>         g_main_loop_run(loop);
> 
> The problem with that is:
>      1. Thread 1 is inside g_main_loop_run().
>      2. Thread 2 sets the timeout, gets stopped after g_timeout_add()
>         and before g_main_loop_run().
>      3. Thread 1 calls timed_out(), which stops thread 2's event loop
>         and removes the source.
>      4. Thread 2 enters g_main_loop_run() which sets "is running" to
>         true and is stuck forever.
> 
> It's a bit contrived because it's unlikely to happen when the timeout is
> large, but it may be more likely with other kinds of events.
> 
> It may further reduce the risk to do:
>         if (!g_main_loop_is_running(loop)) {
>             g_main_loop_run(loop);
>         }
> but because that code can be interrupted, too, it just shifts the
> problem. The real solution would be a g_main_loop_run_if_running() which
> atomically checks the flag and returns immediately if false. Is
> something like that possible with the current API, or are there other
> solutions to the problem?

One more potential problem with such a g_main_loop_run_if_running() if
implemented as g_main_loop_run() without the "loop->is_running = TRUE"
parts: if thread 1 keeps owning the main context forever, will thread 2
get a chance to check it's is_running flag?

In the current implementation of g_main_loop_run(), thread 2 would wait
for ownership of the context here:

      while (loop->is_running && !got_ownership)
	got_ownership = g_main_context_wait (loop->context,
                                             &loop->context->cond,
                                             &loop->context->mutex);

Will g_main_context_wait() ever return if thread 1 doesn't release
ownership? It doesn't look like this will happen.

-- 
Best Regards, Patrick Ohly

The content of this message is my personal opinion only and although
I am an employee of Intel, the statements I make here in no way
represent Intel's position on the issue, nor am I authorized to speak
on behalf of Intel on this matter.


_______________________________________________
gtk-list mailing list
gtk-list@xxxxxxxxx
https://mail.gnome.org/mailman/listinfo/gtk-list




[Index of Archives]     [Touch Screen Library]     [GIMP Users]     [Gnome]     [KDE]     [Yosemite News]     [Steve's Art]

  Powered by Linux