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 742065 - Clutter main_quit() does not terminate GJS programs
Clutter main_quit() does not terminate GJS programs
Status: RESOLVED OBSOLETE
Product: gjs
Classification: Bindings
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: gjs-maint
gjs-maint
: 744082 (view as bug list)
Depends on:
Blocks:
 
 
Reported: 2014-12-28 16:27 UTC by Emmanuele Bassi (:ebassi)
Modified: 2018-01-27 11:58 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description Emmanuele Bassi (:ebassi) 2014-12-28 16:27:08 UTC
a simple example:

const Clutter = imports.gi.Clutter;
const Mainloop = imports.mainloop;

Clutter.init(null);

let s = new Clutter.Stage({ width: 200, height: 200, });
s.connect('destroy', function() { Clutter.main_quit(); });
s.show();

Clutter.main();

if I run it with gjs, and press the window's close button, gjs won't quit after the control has been returned to it.

this does not happen when using GTK+, or when using the Mainloop module instead of Clutter.main()/main_quit().

the equivalent C and Python code does not exhibit issues either.
Comment 1 Emmanuele Bassi (:ebassi) 2014-12-28 16:33:47 UTC
you can verify that the control is returned to gjs after Clutter.main() just by adding a `log('foo')` after it.
Comment 2 Giovanni Campagna 2015-01-01 23:59:30 UTC
Ugh, gjs has

    /* First, get rid of anything left over on the main context */
    while (g_main_context_pending(NULL) &&
           g_atomic_int_get(&pending_idle_toggles) > 0) {
        g_main_context_iteration(NULL, FALSE);
    }

Which happens when the GjsContext is destroyed.

Unfortunately, this conflicts with Clutter locking (because it does not hold the clutter lock around the context_pending() call), and causes a deadlock.

That code was added in be5c12c4dc156712a296044916a4108011fe7b3c, Fix assertions during context dispose, by Colin (cced).
Comment 3 Colin Walters 2015-01-03 03:07:10 UTC
Shutdown cleanup is a nasty business...

Can you post the stack trace?
Comment 4 Emmanuele Bassi (:ebassi) 2015-01-05 18:14:54 UTC
(In reply to comment #2)

> Unfortunately, this conflicts with Clutter locking (because it does not hold
> the clutter lock around the context_pending() call), and causes a deadlock.

it does not explain why this does not deadlock GTK's main loop, since the code is not holding the GDK lock either.
Comment 5 Emmanuele Bassi (:ebassi) 2015-02-06 10:35:01 UTC
*** Bug 744082 has been marked as a duplicate of this bug. ***
Comment 6 Lionel Landwerlin 2015-02-06 10:40:24 UTC
I think that's because of the master clock.
Its GSource is going to kick back in while gjs is running its cleanup.
The GSource takes the clutter global lock, which is already locked upon leaving clutter_main().

In #744082 I suggested to maybe remove the GSource of the master clock, when leaving clutter_main(). It feels like Clutter's internal should stop running when exiting.
Any thoughts?
Comment 7 Emmanuele Bassi (:ebassi) 2015-02-06 11:06:49 UTC
the main issue is that main() → main_quit() → main() is a supported use case, so calling main_quit() should not tear down the global state, unless it can be set up again once main() is called.
Comment 8 Lionel Landwerlin 2015-02-07 23:39:21 UTC
So digging more into this, I take back what I wrote about Gtk.
You can make Gtk+ dead lock has well :

const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;

Gtk.init(null, null);
Gdk.threads_init();

let win = new Gtk.Window();
win.show();

Mainloop.timeout_add(50, function() { Gtk.main_quit(); });

Gtk.main();


The key difference, is that Gtk+ doesn't initialize its threads lock by default, so all gdk_threads_enter/leave() calls have no effect.

Is this something we could consider for Clutter too?
Comment 9 Lionel Landwerlin 2015-02-07 23:42:10 UTC
Just noticed that this bug moved to gjs.
Here is a Gtk+ example that deadlocks entirely on its own :

const Gdk = imports.gi.Gdk;
const Gtk = imports.gi.Gtk;
const Mainloop = imports.mainloop;

Gtk.init(null, null);
Gdk.threads_init();

let win = new Gtk.Window();
win.show();

Mainloop.timeout_add(50, function() { Gtk.main(); });
Mainloop.timeout_add(100, function() { Gtk.main_quit(); });

Gtk.main();


I don't think this is a gjs bug.
Comment 10 GNOME Infrastructure Team 2018-01-27 11:58:49 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/gjs/issues/91.