After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 745248 - Re-entancy issues with GTK event API called from Clutter event handlers
Re-entancy issues with GTK event API called from Clutter event handlers
Status: RESOLVED FIXED
Product: clutter-gtk
Classification: Platform
Component: GtkClutterEmbed
1.6.x
Other Linux
: Normal normal
: ---
Assigned To: clutter-gtk maintainer(s)
clutter-gtk maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2015-02-26 19:00 UTC by Jonas Danielsson
Modified: 2015-09-03 06:15 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
mainWindow: prevent Clutter deadlock (1.25 KB, patch)
2015-02-27 12:52 UTC, Lionel Landwerlin
none Details | Review
mainWindow: prevent Clutter deadlock (1.24 KB, patch)
2015-02-27 12:54 UTC, Lionel Landwerlin
none Details | Review

Description Jonas Danielsson 2015-02-26 19:00:44 UTC
Hi,

So I jhbuilded maps from scratch for the first time in a while today. And found that Maps will freeze completly when clicking the Map.

I bisected clutter (which was a hassle because of libinput API break) and this is what the bisect said:

60dbeb9425f51fc602ba2fe89b2a968ef4b527ed is the first bad commit
commit 60dbeb9425f51fc602ba2fe89b2a968ef4b527ed
Author: Emmanuele Bassi <ebassi@gnome.org>
Date:   Sun Jan 11 16:48:47 2015 +0000

    Try again at using the GDK backend by default
    
    We tried once with commit 398a7ac7 and ended up reverting because of
    regressions in the input layer and on Wayland.
    
    We should try again, now that those regressions have been fixed.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=734587


Before that commit clicking the map works fine.
Comment 1 Jonas Danielsson 2015-02-26 19:11:58 UTC
Ok, so for shits and giggles I removed the line in Maps that did:
    this.view.reactive = true;

And after that I could move the map around, but I got other strange effects.
But maybe that is a clue?
Comment 2 Jonas Danielsson 2015-02-26 19:29:19 UTC
The strange effect being that the map bubbles did not dissapear while panning, which might be because the view is not longer reactive. Since it listens on button-press-event on the ChamplainView clutter actor.
Comment 3 Jonas Danielsson 2015-02-26 20:03:42 UTC
Some more debug, I looked in clutter-gtk, and I did this:

diff --git a/clutter-gtk/gtk-clutter-embed.c b/clutter-gtk/gtk-clutter-embed.c
index 64cc8b6..78de2d1 100644
--- a/clutter-gtk/gtk-clutter-embed.c
+++ b/clutter-gtk/gtk-clutter-embed.c
@@ -954,8 +954,11 @@ gtk_clutter_embed_event (GtkWidget *widget,
                          GdkEvent  *event)
 {
 #if defined(CLUTTER_WINDOWING_GDK)
+  g_print("clutter windowing gdk\n");
   if (clutter_check_windowing_backend (CLUTTER_WINDOWING_GDK))
     clutter_gdk_handle_event (event);
+
+  g_print("handled event\n");
 #endif


And noticed that after I pressed it never printed handled event, (I saw it before). Then I added a bunch of debug in clutter-gdk-event.c, the most interesting being:

diff --git a/clutter/gdk/clutter-event-gdk.c b/clutter/gdk/clutter-event-gdk.c
index 9f7dec7..d68635c 100644
--- a/clutter/gdk/clutter-event-gdk.c
+++ b/clutter/gdk/clutter-event-gdk.c
@@ -103,8 +103,9 @@ clutter_gdk_handle_event (GdkEvent *gdk_event)
   if (stage == NULL)
     return GDK_FILTER_CONTINUE;
 
+  g_print ("acquire lock\n");
   _clutter_threads_acquire_lock ();
-
+  g_print ("lock aquired\n")
   switch (gdk_event->type)
     {
     case GDK_DELETE:


And the output from Maps:

[...]
clutter windowing gdk
acquire lock
lock aquired
handled event
clutter windowing gdk
acquire lock
lock aquired
handled event
clutter windowing gdk
acquire lock
lock aquired
handled event
Gjs-Message: JS LOG: button-press-event
Gjs-Message: JS LOG: button-press-event
clutter windowing gdk
acquire lock

[freezes here]
Comment 4 Lionel Landwerlin 2015-02-27 11:10:52 UTC
Could launch it in gdb and print the backtrace after the lock has appear?
It looks like something is doing something weird with the mainloop.
Comment 5 Lionel Landwerlin 2015-02-27 12:00:54 UTC
Here we go :

^C
Program received signal SIGINT, Interrupt.
syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:38
38	../sysdeps/unix/sysv/linux/x86_64/syscall.S: No such file or directory.
(gdb) bt
  • #0 syscall
    at ../sysdeps/unix/sysv/linux/x86_64/syscall.S line 38
  • #1 g_mutex_lock_slowpath
    at gthread-posix.c line 1308
  • #2 clutter_gdk_handle_event
    at gdk/clutter-event-gdk.c line 106
  • #3 gtk_clutter_embed_event
    at ./gtk-clutter-embed.c line 958
  • #4 _gtk_marshal_BOOLEAN__BOXEDv
    at gtkmarshalers.c line 130
  • #5 _g_closure_invoke_va
    at gclosure.c line 831
  • #6 g_signal_emit_valist
    at gsignal.c line 3214
  • #7 g_signal_emit
    at gsignal.c line 3361
  • #8 gtk_widget_event_internal
    at gtkwidget.c line 7683
  • #9 gtk_widget_send_focus_change
    at gtkwidget.c line 16149
  • #10 do_focus_change
    at gtkwindow.c line 7876
  • #11 gtk_window_real_set_focus
    at gtkwindow.c line 8185
  • #12 g_cclosure_marshal_VOID__OBJECTv
    at gmarshal.c line 2102
  • #13 _g_closure_invoke_va
    at gclosure.c line 831
  • #14 g_signal_emit_valist
    at gsignal.c line 3214
  • #15 g_signal_emit
    at gsignal.c line 3361
  • #16 _g_closure_invoke_va
    at gclosure.c line 831
  • #17 g_signal_emit_valist
    at gsignal.c line 3214
  • #18 g_signal_emit
    at gsignal.c line 3361
  • #19 gtk_widget_grab_focus
    at gtkwidget.c line 8075
  • #20 embed_focus_cb
    at gtk-champlain-embed.c line 397
  • #21 _gtk_marshal_BOOLEAN__BOXED
    at gtkmarshalers.c line 85
  • #22 g_closure_invoke
    at gclosure.c line 768
  • #23 signal_emit_unlocked_R
    at gsignal.c line 3549
  • #24 g_signal_emit_valist
    at gsignal.c line 3315
  • #25 g_signal_emit
    at gsignal.c line 3361
  • #26 gtk_widget_event_internal
    at gtkwidget.c line 7787
  • #27 gtk_widget_send_focus_change
    at gtkwidget.c line 16149
  • #28 do_focus_change
    at gtkwindow.c line 7876
  • #29 gtk_window_real_set_focus
    at gtkwindow.c line 8185
  • #30 g_cclosure_marshal_VOID__OBJECTv
    at gmarshal.c line 2102
  • #31 _g_closure_invoke_va
    at gclosure.c line 831
  • #32 g_signal_emit_valist
    at gsignal.c line 3214
  • #33 g_signal_emit
    at gsignal.c line 3361
  • #34 _g_closure_invoke_va
    at gclosure.c line 831
  • #35 g_signal_emit_valist
    at gsignal.c line 3214
  • #36 g_signal_emit
    at gsignal.c line 3361
  • #37 gtk_widget_grab_focus
    at gtkwidget.c line 8075
  • #38 ffi_call_unix64
    from /usr/lib/x86_64-linux-gnu/libffi.so.6
  • #39 ffi_call
    from /usr/lib/x86_64-linux-gnu/libffi.so.6
  • #40 gjs_invoke_c_function
    at gi/function.cpp line 997
  • #41 function_call
    at gi/function.cpp line 1319
  • #42 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #43 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #44 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #45 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #46 JS_CallFunctionValue(JSContext*, JSObject*, JS::Value, unsigned int, JS::Value*, JS::Value*)
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #47 gjs_call_function_value
    at gjs/jsapi-util.cpp line 724
  • #48 gjs_closure_invoke
    at gi/closure.cpp line 282
  • #49 closure_marshal
    at gi/value.cpp line 160
  • #50 g_closure_invoke
    at gclosure.c line 768
  • #51 signal_emit_unlocked_R
    at gsignal.c line 3549
  • #52 g_signal_emit_valist
    at gsignal.c line 3315
  • #53 g_signal_emit
    at gsignal.c line 3361
  • #54 clutter_actor_event
    at clutter-actor.c line 13797
  • #55 _clutter_actor_handle_event
    at clutter-actor.c line 20436
  • #56 emit_event_chain
    at clutter-main.c line 2136
  • #57 emit_pointer_event
    at clutter-main.c line 2159
  • #58 _clutter_process_event_details
    at clutter-main.c line 2507
  • #59 _clutter_process_event
    at clutter-main.c line 2667
  • #60 _clutter_stage_process_queued_events
    at clutter-stage.c line 1082
  • #61 master_clock_process_stage_events
    at gdk/clutter-master-clock-gdk.c line 151
  • #62 clutter_master_clock_gdk_update
    at gdk/clutter-master-clock-gdk.c line 287
  • #63 g_closure_invoke
  • #64 signal_emit_unlocked_R
    at gsignal.c line 3549
  • #65 g_signal_emit_valist
    at gsignal.c line 3305
  • #66 g_signal_emit_by_name
    at gsignal.c line 3401
  • #67 gdk_frame_clock_paint_idle
    at gdkframeclockidle.c line 380
  • #68 gdk_threads_dispatch
    at gdk.c line 717
  • #69 g_timeout_dispatch
    at gmain.c line 4545
  • #70 g_main_dispatch
    at gmain.c line 3122
  • #71 g_main_context_dispatch
    at gmain.c line 3737
  • #72 g_main_context_iterate
    at gmain.c line 3808
  • #73 g_main_context_iteration
    at gmain.c line 3869
  • #74 g_application_run
    at gapplication.c line 2308
  • #75 ffi_call_unix64
    from /usr/lib/x86_64-linux-gnu/libffi.so.6
  • #76 ffi_call
    from /usr/lib/x86_64-linux-gnu/libffi.so.6
  • #77 gjs_invoke_c_function
    at gi/function.cpp line 997
  • #78 function_call
    at gi/function.cpp line 1319
  • #79 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #80 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #81 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #82 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #83 JS::Evaluate(JSContext*, JS::Handle<JSObject*>, JS::CompileOptions, unsigned short const*, unsigned long, JS::Value*)
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #84 JS::Evaluate(JSContext*, JS::Handle<JSObject*>, JS::CompileOptions, char const*, unsigned long, JS::Value*)
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #85 gjs_eval_with_scope
    at gjs/jsapi-util.cpp line 1325
  • #86 gjs_context_eval
    at gjs/context.cpp line 646
  • #87 main
    at gjs/console.cpp line 140

Comment 6 Lionel Landwerlin 2015-02-27 12:52:22 UTC
Created attachment 298084 [details] [review]
mainWindow: prevent Clutter deadlock

This is a pretty ugly workaround.
Comment 7 Lionel Landwerlin 2015-02-27 12:54:45 UTC
Created attachment 298085 [details] [review]
mainWindow: prevent Clutter deadlock

This is a pretty ugly workaround.
Comment 8 Jonas Danielsson 2015-02-27 13:06:20 UTC
Hi Lionel, thanks for looking into this!

I don't quite understand tho. This implies that Maps is doing something wrong?
It worked fine before the switch to GDK backend. Is it not working because Maps connects to the button-press-event twice? If so the workaround in your patch is quite fragile :) Since when a map bubble appear we will connect to that event again, to see when it should be dismissed.

Should this not be fixed in clutter-gtk or in clutter? Is there some documentation that shows that Maps is misusing the API?

Thanks
Comment 9 Jonas Danielsson 2015-02-27 13:11:10 UTC
Or is it the grab_focus call that creates some circular thing? Is it not allowed from an event handler?
Comment 10 Lionel Landwerlin 2015-02-27 13:12:17 UTC
Hi Jonas,

As I wrote it's an ugly workaround. I'm not sure how to actually fix this.

The root of the issue is that maps is listening to a Clutter event signal and then trying to take a grab using GTK+, which generates new events, then processed by Clutter again.
You can see this issue :

ClutterEvent -> GtkEvent -> ClutterEvent (deadlock).
Comment 11 Lionel Landwerlin 2015-02-27 13:19:38 UTC
Maybe the right thing to do would be to listen to GTK+ events instead of Clutter, and just use Clutter as a rendering API.
Comment 12 Jonas Danielsson 2015-02-27 13:25:25 UTC
Yeah, maybe... Not sure why these button-press-events listens to the Clutter actor instead of the GtkClutterEmbed widget, will have to investigate if there is a real reason.

And we are interacting with the clutter based libchamplain map widget. So, will have to see that it works out with its events as well. I guess. Or, mandate, as with your work-around patch above, that no code that generates clutter events may be called from a clutter event handler directly.
Comment 13 Jonas Danielsson 2015-02-27 19:30:38 UTC
I commited a work-around fix, sort of the one Lionel suggested, in Maps. Not sure if more needs to be done with this bug? Should it stay open?
Comment 14 Lionel Landwerlin 2015-03-02 12:13:02 UTC
I think there isn't much we can do here.
If you could find a way to make all event handling using GTK+, that would be the sanest solution at the moment.

Of course the ultimate answer would be to have something like Clutter inside GTK+ to avoid this kind of issues (GTK+4?).

If you don't have time to investigate the GTK+ events, I might give it a try this week.
Comment 15 Jonas Danielsson 2015-03-02 12:30:20 UTC
(In reply to Lionel Landwerlin from comment #14)
> I think there isn't much we can do here.
> If you could find a way to make all event handling using GTK+, that would be
> the sanest solution at the moment.
> 
> Of course the ultimate answer would be to have something like Clutter inside
> GTK+ to avoid this kind of issues (GTK+4?).
> 
> If you don't have time to investigate the GTK+ events, I might give it a try
> this week.

Well, libchamplain (the map widget) is clutter based, so I don't know how feasible it would be to be pure GTK+ in event handling. But it seems that the case that deadlocked is the only case of calling something that generates events from an event handler, so I hope we are good with it. I think that case also was some kind of hack to get panning with keyboard to work. Don't remember exactly.
Comment 16 Matthias Clasen 2015-03-02 16:50:50 UTC
putting this on the blocker list for tracking
Comment 17 Matthias Clasen 2015-03-05 18:24:17 UTC
So, maps seems to work just fine here (under X).  Is anything left to do here, or did the workaround from comment 13 fix this for now ?
Comment 18 Emmanuele Bassi (:ebassi) 2015-03-09 17:56:57 UTC
Leaving a comment following a discussion on #clutter (that I don't have any more because I lost the backtrace):

A potential solution for the issue is to add a toggle inside GtkClutterEmbed that disables all event delivery from the Clutter side. GtkClutterEmbed would then consume only the windowing system events coming from GDK. This disables all event handling from the scene graph, thus making Clutter only the drawing API. The GtkWidgets embedded into the scene graph would still obviously keep working. On the other hand, if your application is using Clutter as a full scene graph, with input only on ClutterActors (for instance, you're writing a small game, or a viewer), then you'd still be safe.

I can try sneaking in this API before 3.16.

The situation definitely warrants a warning in the API reference of Clutter-GTK, though.
Comment 19 Emmanuele Bassi (:ebassi) 2015-06-17 12:01:51 UTC
Re-assigning to clutter-gtk.

I'm not sold on the API to disable event handling — mostly because it's hard to know when to use it.

I've added a note to the API reference, though, so I can point people at it.

I'll keep the bug open anyway, in case I change my mind, or find a decent approach.
Comment 20 Emmanuele Bassi (:ebassi) 2015-06-17 12:03:06 UTC
Pushed a documentation fix as commit 464b0001e3464374e2b361caa6ef45e8584bf30e