[PATCH 1/2] Convert python signal handlers to GLib signal handlers
David Shea
dshea at redhat.com
Wed Sep 24 21:21:00 UTC 2014
If a signal is handled through python while the Gtk main loop is
running, we get stuck waiting for a Gtk/GLib event before it releases
the interperter lock, so just handle them as GLib events instead.
---
pyanaconda/ui/gui/__init__.py | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/pyanaconda/ui/gui/__init__.py b/pyanaconda/ui/gui/__init__.py
index df98360..6a3dca3 100644
--- a/pyanaconda/ui/gui/__init__.py
+++ b/pyanaconda/ui/gui/__init__.py
@@ -18,7 +18,7 @@
#
# Red Hat Author(s): Chris Lumens <clumens at redhat.com>
#
-import inspect, os, sys, time, site
+import inspect, os, sys, time, site, signal
import meh.ui.gui
from contextlib import contextmanager
@@ -541,6 +541,38 @@ class GraphicalUserInterface(UserInterface):
# Export the scale so that Gtk programs launched by anaconda are also scaled
os.environ["GDK_SCALE"] = "2"
+ def _convertSignals(self):
+ # What tends to happen when we receive a signal is that the signal will
+ # be received by the python interpreter's C handler, python will do
+ # what it needs to do to set the python handler we registered to run,
+ # the C handler returns, and then nothing happens because Gtk is
+ # holding the global interpreter lock. The signal then gets delivered
+ # to our python code when you move the mouse or something. We can get
+ # around this by doing signals the GLib way. The conversion assumes
+ # that none of our signal handlers care about the frame parameter,
+ # which is generally true.
+ #
+ # After the unix_signal_add call, signal.getsignal will tell a half
+ # truth: the method returned will still be called, by way of
+ # _signal_converter, but GLib will have replaced the actual signal
+ # handler for that signal.
+
+ # Convert everything except SIGCHLD, because that's a different can of worms
+
+ def _signal_converter(user_data):
+ (handler, signum) = user_data
+ handler(signum)
+
+ for signum in range(1, signal.SIGCHLD) + range(signal.SIGCHLD + 1, signal.NSIG):
+ handler = signal.getsignal(signum)
+ if handler and handler not in (signal.SIG_DFL, signal.SIG_IGN):
+ # NB: if you are looking at the glib documentation you are in for
+ # some surprises because gobject-introspection is a minefield.
+ # g_unix_signal_add_full comes out as GLib.unix_signal_add, and
+ # g_unix_signal_add doesn't come out at all.
+ GLib.unix_signal_add(GLib.PRIORITY_DEFAULT, signum,
+ _signal_converter, (handler, signum))
+
@property
def tty_num(self):
return 6
@@ -648,6 +680,10 @@ class GraphicalUserInterface(UserInterface):
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(), provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
+ # The interaction between python signal handlers and Gtk is problematic,
+ # so convert them all to GLib signal handlers.
+ self._convertSignals()
+
# try to make sure a logo image is present
self._assureLogoImage()
--
2.1.0
More information about the anaconda-patches
mailing list