summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohan Dahlin <johan@gnome.org>2008-01-03 14:07:02 +0000
committerJohan Dahlin <johan@src.gnome.org>2008-01-03 14:07:02 +0000
commit302646e6d0eba9a79c8adf52e67ec31f214726d9 (patch)
tree8ab7a4889b6d748feb14d0b1e7a47e688c1b64d6
parente624121ffa7ece38d111448ca5064d0528101967 (diff)
downloadpygobject-302646e6d0eba9a79c8adf52e67ec31f214726d9.tar.gz
Backport from trunk:
2008-01-03 Johan Dahlin <johan@gnome.org> Backport from trunk: * configure.ac: * gobject/pygmainloop.c (pyg_signal_watch_prepare): Optinally use PySignal_SetWakeupFd to avoid having to do a timeout to find out if there are any pending signals from python. Fixes #481569 svn path=/branches/pygobject-2-14/; revision=724
-rw-r--r--ChangeLog10
-rw-r--r--configure.ac16
-rw-r--r--gobject/pygmainloop.c74
3 files changed, 89 insertions, 11 deletions
diff --git a/ChangeLog b/ChangeLog
index c28d2dc3..87b6a979 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2008-01-03 Johan Dahlin <johan@gnome.org>
+
+ Backport from trunk:
+
+ * configure.ac:
+ * gobject/pygmainloop.c (pyg_signal_watch_prepare): Optinally
+ use PySignal_SetWakeupFd to avoid having to do a timeout to find
+ out if there are any pending signals from python.
+ Fixes #481569
+
2007-10-16 Damien Carbery <damien.carbery@sun.com>
reviewed by: Johan Dahlin.
diff --git a/configure.ac b/configure.ac
index 13861514..349edfad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,22 @@ AM_PATH_PYTHON(2.3.5)
AM_CHECK_PYTHON_HEADERS(,[AC_MSG_ERROR(could not find Python headers)])
+AC_MSG_CHECKING([for PySignal_SetWakeupFd in Python.h])
+py_prefix=`$PYTHON -c "import sys; print sys.prefix"`
+PYTHON_INCLUDES="-I${py_prefix}/include/python${PYTHON_VERSION}"
+old_CPPFLAGS=$CPPFLAGS
+CPPFLAGS="$PYTHON_INCLUDES"
+AC_TRY_COMPILE([#include <Python.h>],
+ [PySignal_SetWakeupFd(0);],
+ setwakeupfd_ok=yes,
+ setwakeupfd_ok=no)
+AC_MSG_RESULT($setwakeupfd_ok)
+if test "x$setwakeupfd_ok" != xno; then
+ AC_DEFINE(HAVE_PYSIGNAL_SETWAKEUPFD, 1,
+ [Define to 1 if PySignal_SetWakeupFd is available])
+fi
+CPPFLAGS=$old_CPPFLAGS
+
PLATFORM=`$PYTHON -c "from distutils import util; print util.get_platform()"`
AC_SUBST(PLATFORM)
diff --git a/gobject/pygmainloop.c b/gobject/pygmainloop.c
index 66fc9526..c80c41fe 100644
--- a/gobject/pygmainloop.c
+++ b/gobject/pygmainloop.c
@@ -102,22 +102,60 @@ pyg_get_current_main_loop (void)
}
#endif /* DISABLE_THREADING */
+typedef struct {
+ GSource source;
+ int fds[2];
+ GPollFD fd;
+} PySignalWatchSource;
+
static gboolean
pyg_signal_watch_prepare(GSource *source,
int *timeout)
{
+ PySignalWatchSource *real_source = (PySignalWatchSource *)source;
+
/* Python only invokes signal handlers from the main thread,
* so if a thread other than the main thread receives the signal
* from the kernel, PyErr_CheckSignals() from that thread will
- * do nothing. So, we need to time out and check for signals
- * regularily too.
- * Also, on Windows g_poll() won't be interrupted by a signal
- * (AFAIK), so we need the timeout there too.
+ * do nothing.
+ */
+
+ /* On Windows g_poll() won't be interrupted by a signal
+ * (AFAIK), so we need the timeout there too, even if there's
+ * only one thread.
*/
#ifndef PLATFORM_WIN32
- if (pyg_threads_enabled)
+ if (!pyg_threads_enabled)
+ return FALSE;
#endif
- *timeout = 1000;
+
+#ifdef HAVE_PYSIGNAL_SETWAKEUPFD
+ if (real_source->fds[0] != 0)
+ return FALSE;
+
+ /* Unfortunately we need to create a new pipe here instead of
+ * reusing the pipe inside the GMainContext.
+ * Ideally an api should be added to GMainContext which allows us
+ * to reuse that pipe which would suit us perfectly fine.
+ */
+ if (pipe(real_source->fds) < 0)
+ g_error("Cannot create main loop pipe: %s\n",
+ g_strerror(errno));
+
+ real_source->fd.fd = real_source->fds[0];
+ real_source->fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ g_source_add_poll(source, &real_source->fd);
+
+ PySignal_SetWakeupFd(real_source->fds[1]);
+
+#else /* !HAVE_PYSIGNAL_SETWAKEUPFD */
+ /* If we're using 2.5 or an earlier version of python we
+ * will default to a timeout every second, be aware,
+ * this will cause unnecessary wakeups, see
+ * http://bugzilla.gnome.org/show_bug.cgi?id=481569
+ */
+ *timeout = 1000;
+#endif /* HAVE_PYSIGNAL_SETWAKEUPFD */
return FALSE;
}
@@ -143,27 +181,41 @@ pyg_signal_watch_check(GSource *source)
}
static gboolean
-pyg_signal_watch_dispatch(GSource *source,
- GSourceFunc callback,
- gpointer user_data)
+pyg_signal_watch_dispatch(GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
{
/* We should never be dispatched */
g_assert_not_reached();
return TRUE;
}
+static void
+pyg_signal_watch_finalize(GSource *source)
+{
+ PySignalWatchSource *real_source = (PySignalWatchSource*)source;
+
+ if (source != NULL) {
+ if (real_source->fds[0] != 0)
+ close(real_source->fds[0]);
+
+ if (real_source->fds[1] != 0)
+ close(real_source->fds[1]);
+ }
+}
+
static GSourceFuncs pyg_signal_watch_funcs =
{
pyg_signal_watch_prepare,
pyg_signal_watch_check,
pyg_signal_watch_dispatch,
- NULL
+ pyg_signal_watch_finalize
};
static GSource *
pyg_signal_watch_new(void)
{
- return g_source_new(&pyg_signal_watch_funcs, sizeof(GSource));
+ return g_source_new(&pyg_signal_watch_funcs, sizeof(PySignalWatchSource));
}
static int