- closes #17
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gnome-abrt | 4 ++-
src/gnome_abrt/Makefile.am | 1 +
src/gnome_abrt/controller.py.in | 19 +++--------
src/gnome_abrt/signals.py | 71 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 79 insertions(+), 16 deletions(-)
create mode 100644 src/gnome_abrt/signals.py
diff --git a/src/gnome-abrt b/src/gnome-abrt
index a277d36..8d4cf36 100755
--- a/src/gnome-abrt
+++ b/src/gnome-abrt
@@ -36,6 +36,7 @@ from gi.repository import Gio
import gnome_abrt
from gnome_abrt.views import OopsWindow
from gnome_abrt.controller import Controller
+from gnome_abrt.signals import glib_sigchld_signal_handler
from gnome_abrt.problems import MultipleSources
from gnome_abrt.directory_problems import DirectoryProblemSource
from gnome_abrt.dbus_problems import DBusProblemSource
@@ -189,7 +190,8 @@ class OopsApplication(Gtk.Application):
self.source = MultipleSources(sources)
- controller = Controller(self.source)
+ controller = Controller(self.source,
+ glib_sigchld_signal_handler)
main_window = OopsWindow(self, self.source, controller)
main_window.show_all()
self.add_window (main_window)
diff --git a/src/gnome_abrt/Makefile.am b/src/gnome_abrt/Makefile.am
index c390a2b..2635832 100644
--- a/src/gnome_abrt/Makefile.am
+++ b/src/gnome_abrt/Makefile.am
@@ -11,6 +11,7 @@ gnome_abrtexec_PYTHON = \
directory_problems.py \
errors.py \
problems.py \
+ signals.py \
tools.py \
views.py \
l10n.py \
diff --git a/src/gnome_abrt/controller.py.in b/src/gnome_abrt/controller.py.in
index f3898ac..f48e26d 100644
--- a/src/gnome_abrt/controller.py.in
+++ b/src/gnome_abrt/controller.py.in
@@ -18,24 +18,13 @@
import logging
import os
import sys
-import signal
class Controller(object):
- def __init__(self, source):
+ def __init__(self, source, sigchld_assign=None):
self.source = source
self.run_event_fn = self._first_event_run
-
- #pylint: disable=W0613
- def _handle_signal(self, signum):
- while True:
- try:
- os.wait3(os.WNOHANG)
- except OSError as ex:
- logging.debug(ex.message)
- break
-
- self.source.refresh()
+ self._sigchld_assign = sigchld_assign
def report(self, problem):
if not problem:
@@ -59,8 +48,8 @@ class Controller(object):
self.run_event_fn("open-gui", problem)
def _first_event_run(self, event, problem):
- signal.signal(signal.SIGCHLD,
- lambda signum, frame: self._handle_signal(signum))
+ if self._sigchld_assign is not None:
+ self._sigchld_assign(self.source.refresh)
self.run_event_fn = self._run_event_on_problem
self.run_event_fn(event, problem)
diff --git a/src/gnome_abrt/signals.py b/src/gnome_abrt/signals.py
new file mode 100644
index 0000000..d0d0b40
--- /dev/null
+++ b/src/gnome_abrt/signals.py
@@ -0,0 +1,71 @@
+## Copyright (C) 2013 ABRT team <abrt-devel-list(a)redhat.com>
+## Copyright (C) 2013 Red Hat, Inc.
+
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA
+
+import os
+import signal
+import logging
+import fcntl
+
+#pylint: disable=E0611
+from gi.repository import GLib
+
+#pylint: disable=W0613
+def _handle_signal_sigchld(callback, data):
+ while True:
+ try:
+ os.wait3(os.WNOHANG)
+ except OSError as ex:
+ # Breaks once no child is waiting
+ logging.debug(ex.message)
+ break
+
+ if data is not None:
+ callback(data)
+ else:
+ callback()
+
+def sigchld_signal_handler(callback, data=None):
+ signal.signal(signal.SIGCHLD,
+ lambda signum, frame: _handle_signal_sigchld(callback, data))
+
+
+#pylint: disable=W0613
+def _gsource_handle_signal(source, condition, data):
+ # Read all bytes, SIGCHLD could be received more than once but we want to
+ # call the callback only once. So, read all bytes from GIOChannel
+ while source.read():
+ pass
+
+ if data[1] is not None:
+ data[0](data[1])
+ else:
+ data[0]()
+
+def _giochannel_notice_sigchld_signal(wfd):
+ os.write(wfd, '1')
+
+def glib_sigchld_signal_handler(callback, data=None):
+ pipes = os.pipe()
+ fcntl.fcntl(pipes[0], fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+ fcntl.fcntl(pipes[1], fcntl.F_SETFD, fcntl.FD_CLOEXEC)
+
+ sigchld_signal_handler(_giochannel_notice_sigchld_signal, pipes[1])
+
+ channel = GLib.IOChannel(pipes[0])
+ channel.set_flags(GLib.IOFlags.NONBLOCK)
+ channel.add_watch(GLib.IOCondition.IN,
+ _gsource_handle_signal, (callback, data))
--
1.8.1.4