diff options
author | Johan Dahlin <johan@gnome.org> | 2008-01-03 14:07:02 +0000 |
---|---|---|
committer | Johan Dahlin <johan@src.gnome.org> | 2008-01-03 14:07:02 +0000 |
commit | 302646e6d0eba9a79c8adf52e67ec31f214726d9 (patch) | |
tree | 8ab7a4889b6d748feb14d0b1e7a47e688c1b64d6 | |
parent | e624121ffa7ece38d111448ca5064d0528101967 (diff) | |
download | pygobject-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-- | ChangeLog | 10 | ||||
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | gobject/pygmainloop.c | 74 |
3 files changed, 89 insertions, 11 deletions
@@ -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 |