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 760012 - Segfault when closing app right after window is shown
Segfault when closing app right after window is shown
Status: RESOLVED FIXED
Product: libchamplain
Classification: Core
Component: General
unspecified
Other Linux
: Normal normal
: ---
Assigned To: libchamplain-maint
libchamplain-maint
: 760643 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2015-12-30 20:24 UTC by Hashem Nasarat
Modified: 2016-02-25 19:40 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
path-layer: Add guards to invalidate callback (1003 bytes, patch)
2016-01-02 14:28 UTC, Jonas Danielsson
none Details | Review
champlain-view: Remove children from user_layers in dispose (801 bytes, patch)
2016-02-16 10:11 UTC, Jonas Danielsson
none Details | Review
champlain-view: Remove children from user_layers in dispose (872 bytes, patch)
2016-02-23 18:45 UTC, Jonas Danielsson
none Details | Review

Description Hashem Nasarat 2015-12-30 20:24:45 UTC
If I run the app and then immediately close the window, the app segfaults. The segfault occurs if I close the app with Alt+F4 or by clicking the close button in the headerbar.


(org.gnome.Maps:31332): Clutter-CRITICAL **: clutter_canvas_set_size: assertion 'CLUTTER_IS_CANVAS (canvas)' failed

Program received signal SIGSEGV, Segmentation fault.
0x00007fffe45b1d09 in clutter_actor_set_size (self=0xcb1aa0, width=256, height=256) at clutter-actor.c:10716
10716     g_return_if_fail (CLUTTER_IS_ACTOR (self));
(gdb) bt
  • #0 clutter_actor_set_size
    at clutter-actor.c line 10716
  • #1 invalidate_canvas
    at champlain-path-layer.c line 483
  • #2 g_main_dispatch
    at gmain.c line 3154
  • #3 g_main_context_dispatch
    at gmain.c line 3769
  • #4 g_main_context_iterate
    at gmain.c line 3840
  • #5 g_main_context_iteration
    at gmain.c line 3901
  • #6 g_application_run
    at gapplication.c line 2347
  • #7 ffi_call_unix64
    from /usr/lib/x86_64-linux-gnu/libffi.so.6
  • #8 ffi_call
    from /usr/lib/x86_64-linux-gnu/libffi.so.6
  • #9 gjs_invoke_c_function
    at gi/function.cpp line 999
  • #10 function_call
    at gi/function.cpp line 1322
  • #11 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #12 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #13 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #14 ??
    from /usr/lib/x86_64-linux-gnu/libmozjs-24.so.0
  • #15 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
  • #16 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
  • #17 gjs_eval_with_scope
    at gjs/jsapi-util.cpp line 1325
  • #18 gjs_context_eval
    at gjs/context.cpp line 645
  • #19 main
    at gjs/console.cpp line 146

Comment 1 Jonas Danielsson 2016-01-02 14:28:02 UTC
I think this is a champlain matter.

Thanks for filing!
Comment 2 Jonas Danielsson 2016-01-02 14:28:33 UTC
Created attachment 318162 [details] [review]
path-layer: Add guards to invalidate callback

We can get race condition when disposing a ChamplainPathLayer.
Make sure we do not end up with a segmentation fault.
Comment 3 Jiri Techet 2016-01-05 16:13:14 UTC
Hmm, I don't think this is the right way to fix the problem - there are lots of idle calls like this and if things the idle calls are properly reffed, they shouldn't get destroyed before the idle is called.

First of all we should know why this happens - the invalidate_canvas() function is always called from schedule_redraw() which ref()s the layer so it shouldn't get destroyed before the idle function is called. The path_actor is a child of the layer so it shouldn't be destroyed either.

It's true that path_actor itself isn't explicitly reffed for the priv->path_actor variable (and then unreffed in dispose) but that shouldn't matter IMO as if the layer isn't destroyed, the child actor shouldn't get destroyed either.

I don't seem to be able to reproduce the problem with the libchamplain demos - could you investigate more when this happens?
Comment 4 Jonas Danielsson 2016-01-11 08:11:51 UTC
(In reply to Jiri Techet from comment #3)
> Hmm, I don't think this is the right way to fix the problem - there are lots
> of idle calls like this and if things the idle calls are properly reffed,
> they shouldn't get destroyed before the idle is called.

Agreed. Trying more it seems that with only the guard for IS_PATH_LAYER ... it still segfaults, it is the guard against canvas that helps... so seems layer is properly reffed but the canvas is what has failed ... which is really weird.

> 
> First of all we should know why this happens - the invalidate_canvas()
> function is always called from schedule_redraw() which ref()s the layer so
> it shouldn't get destroyed before the idle function is called. The
> path_actor is a child of the layer so it shouldn't be destroyed either.

Agreed. I wonder tho if it might be the canvas_set_size that triggers this.

> 
> It's true that path_actor itself isn't explicitly reffed for the
> priv->path_actor variable (and then unreffed in dispose) but that shouldn't
> matter IMO as if the layer isn't destroyed, the child actor shouldn't get
> destroyed either.
> 
> I don't seem to be able to reproduce the problem with the libchamplain demos
> - could you investigate more when this happens?

I will try! Thanks!
Comment 5 Jonas Danielsson 2016-01-11 08:19:44 UTC
(In reply to Jonas Danielsson from comment #4)
> (In reply to Jiri Techet from comment #3)
> > Hmm, I don't think this is the right way to fix the problem - there are lots
> > of idle calls like this and if things the idle calls are properly reffed,
> > they shouldn't get destroyed before the idle is called.
> 
> Agreed. Trying more it seems that with only the guard for IS_PATH_LAYER ...
> it still segfaults, it is the guard against canvas that helps... so seems
> layer is properly reffed but the canvas is what has failed ... which is
> really weird.
> 
> > 
> > First of all we should know why this happens - the invalidate_canvas()
> > function is always called from schedule_redraw() which ref()s the layer so
> > it shouldn't get destroyed before the idle function is called. The
> > path_actor is a child of the layer so it shouldn't be destroyed either.
> 
> Agreed. I wonder tho if it might be the canvas_set_size that triggers this.
> 
> > 
> > It's true that path_actor itself isn't explicitly reffed for the
> > priv->path_actor variable (and then unreffed in dispose) but that shouldn't
> > matter IMO as if the layer isn't destroyed, the child actor shouldn't get
> > destroyed either.
> > 
> > I don't seem to be able to reproduce the problem with the libchamplain demos
> > - could you investigate more when this happens?
> 
> I will try! Thanks!

So I added this print to invalidate_canvas:

g_print ("width: %f, height: %f, canvas: %p\n", width, height, priv->canvas);

And got these while reproducing:

width: 870,000000, height: 622,000000, canvas: 0x26cc660
width: 256,000000, height: 256,000000, canvas: (nil)
*segfault*

So canvas is NULL when it gets here, and since width/height is 256 priv->view is also NULL. Which means this is after dispose has run, setting view to NULL. And dispose also does priv->canvas = NULL;

So it seems that invalidate_canvas is being called after dispose has run. So something is off with the reffing.
Comment 6 Jonas Danielsson 2016-01-11 08:58:45 UTC
It does not happen all the time, so it is some kind of race somewhere. I could not reproduce with a modified launcher-js or with standard launcher-gtk yet.
Comment 7 Jonas Danielsson 2016-01-15 06:10:31 UTC
*** Bug 760643 has been marked as a duplicate of this bug. ***
Comment 8 Jonas Danielsson 2016-01-15 06:13:15 UTC
I do not see this happening on my systems Maps, only the jhbuild one. So this might be a candidate for git bisect.

Hashem: Up for it?

Dunno which component though, I guess trying with an older champlain, if that does not reproduce, then git bisect with champlain, but it might also be Maps (but I do not really think so we haven't changed how we use routeLayer in a long time), GTK+, or GJS I think...
Comment 9 Jiri Techet 2016-01-15 13:44:00 UTC
Couldn't it be an introspection annotations problem somewhere so e.g. the layer gets passed with (transfer none) to some C code and then it's unreffed when the object that contains it gets destroyed? This doesn't seem to happen on the libchamplain side though - the champlain_view_add_layer() uses default (transfer full) and I don't see other place where this could happen.
Comment 10 Damián Nohales 2016-02-15 13:42:12 UTC
The problem occurs after closing Maps once you searched for a route using the sidebar. I tried to use downgraded versions of libchamplain, clutter and clutter-gtk (the ones for F22), but it throws segfaults there too. I tried to test with downgraded versions of glib and gjs too, but I had problems when trying to compile glib and the gjs version was incompatible. Anyway, there are more tests to be done, like playing with different versions of gobject-introspection.

Are you sure this doesn't happen in F22/F23?
Comment 11 Jonas Danielsson 2016-02-16 10:11:13 UTC
Created attachment 321351 [details] [review]
champlain-view: Remove children from user_layers in dispose
Comment 12 Jonas Danielsson 2016-02-16 10:11:45 UTC
(In reply to Jonas Danielsson from comment #11)
> Created attachment 321351 [details] [review] [review]
> champlain-view: Remove children from user_layers in dispose

Does this solve it for others? I could not reproduce when this is used.
Comment 13 Jiri Techet 2016-02-17 20:12:28 UTC
Jonas, can you explain why this is needed? The whole ClutterActor hierarchy should be destroyed together with ChamplainView. If it is needed to destroy the actor explicitly, it would be good to add some comment in the patch why - right now it's not completely obvious.
Comment 14 Jonas Danielsson 2016-02-21 14:32:45 UTC
(In reply to Jiri Techet from comment #13)
> Jonas, can you explain why this is needed? The whole ClutterActor hierarchy
> should be destroyed together with ChamplainView. If it is needed to destroy
> the actor explicitly, it would be good to add some comment in the patch why
> - right now it's not completely obvious.

no :/

I thought as you that some annotation might be wrong triggering a refcount error. But didn't find one. And I saw this in dispose and got suspicous since user_layers are alloced but never explicitly de-allocated. And doing this seem to fix the issue. But might be by accident since this should be cleaned up by the view cleaning up it's children and so on and so on, right?

Might be the gjs gc kicking in after setting the user_layers to NULL? No idea.


Btw:
Any chance for a release soon? Maps 3.19.90 depends on that enum fix that is unreleased.
Comment 15 Jiri Techet 2016-02-22 10:23:31 UTC
Yes, can make a release by the end of the week.

Does the patch fix the issue for you? If so maybe it's a good idea to apply it together with some comment saying it's actually a hack and we don't know what's going on but that it fixes this particular issue.
Comment 16 Jonas Danielsson 2016-02-22 11:40:27 UTC
(In reply to Jiri Techet from comment #15)
> Yes, can make a release by the end of the week.
>

Awesome!
 
> Does the patch fix the issue for you? If so maybe it's a good idea to apply
> it together with some comment saying it's actually a hack and we don't know
> what's going on but that it fixes this particular issue.

I think it did, I tried "a bunch of times" at least :)

A question: champlain_view_add_layer does not have a "(transfer full):" on the layer so I guess that means we think that the caller owns the layer? Shouldn't we then make sure that it does not get destroyed here? Or should we ref it in in champlain_view_add_layer?
Comment 17 Jiri Techet 2016-02-22 21:54:47 UTC
> A question: champlain_view_add_layer does not have a "(transfer full):" on
> the layer so I guess that means we think that the caller owns the layer?
> Shouldn't we then make sure that it does not get destroyed here? Or should
> we ref it in in champlain_view_add_layer?

Isn't (transfer full) the default? At least that's how I understand the "default annotations" part here https://wiki.gnome.org/Projects/GObjectIntrospection/Annotations#Transfer

I don't know what exactly happens during ClutterActor destruction - I'd suppose children are disposed before parents in which case it should work correctly even without your patch but maybe something else happens before which breaks thing.

Anyway, I think your patch is fine - just maybe add some comment explaining why we do it.
Comment 18 Jonas Danielsson 2016-02-23 18:45:10 UTC
Created attachment 322160 [details] [review]
champlain-view: Remove children from user_layers in dispose
Comment 19 Jiri Techet 2016-02-25 19:40:19 UTC
Applied, thanks.