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