cpython: 1d8a57deddc4 (original) (raw)

Mercurial > cpython

changeset 69934:1d8a57deddc4

Issue #8407: Add pthread_kill(), sigpending() and sigwait() functions to the signal module. [#8407]

Victor Stinner victor.stinner@haypocalc.com
date Sun, 08 May 2011 01:46:11 +0200
parents 6aea90327020
children f8c49a930015
files Doc/library/os.rst Doc/library/signal.rst Doc/whatsnew/3.3.rst Lib/test/test_signal.py Misc/NEWS Modules/signalmodule.c configure configure.in pyconfig.h.in
diffstat 9 files changed, 287 insertions(+), 42 deletions(-)[+] [-] Doc/library/os.rst 2 Doc/library/signal.rst 53 Doc/whatsnew/3.3.rst 9 Lib/test/test_signal.py 141 Misc/NEWS 3 Modules/signalmodule.c 102 configure 5 configure.in 5 pyconfig.h.in 9

line wrap: on

line diff

--- a/Doc/library/os.rst +++ b/Doc/library/os.rst @@ -2284,6 +2284,8 @@ written in Python, such as a mail server will be set to sig. The Windows version of :func:kill additionally takes process handles to be killed.

--- a/Doc/library/signal.rst +++ b/Doc/library/signal.rst @@ -179,6 +179,29 @@ The :mod:signal module defines the fol will then be called. Returns nothing. Not on Windows. (See the Unix man page :manpage:signal(2).)

+ +.. function:: pthread_kill(thread_id, signum) +

.. function:: pthread_sigmask(how, mask) @@ -206,6 +229,8 @@ The :mod:signal module defines the fol Availability: Unix. See the man page :manpage:sigprocmask(3) and :manpage:pthread_sigmask(3) for further information.

@@ -283,6 +308,34 @@ The :mod:signal module defines the fol :const:SIGTERM. A :exc:ValueError will be raised in any other case. +.. function:: sigpending() +

+ +.. function:: sigwait(sigset) +

+ .. _signal-example: Example

--- a/Doc/whatsnew/3.3.rst +++ b/Doc/whatsnew/3.3.rst @@ -123,10 +123,13 @@ sys signal ------ -* The :mod:signal module has a new :func:~signal.pthread_sigmask function

--- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -8,6 +8,10 @@ import signal import subprocess import traceback import sys, os, time, errno +try:

+except ImportError:

if sys.platform in ('os2', 'riscos'): raise unittest.SkipTest("Can't test signal on %s" % sys.platform) @@ -187,7 +191,7 @@ class InterProcessSignalTests(unittest.T @unittest.skipIf(sys.platform == "win32", "Not valid on Windows") -class BasicSignalTests(unittest.TestCase): +class PosixTests(unittest.TestCase): def trivial_signal_handler(self, *args): pass @@ -484,50 +488,121 @@ class ItimerTest(unittest.TestCase): self.assertEqual(self.hndl_called, True) -@unittest.skipUnless(hasattr(signal, 'pthread_sigmask'),

class PendingSignalsTests(unittest.TestCase): """

+ def handler(self, signum, frame): 1/0 def read_sigmask(self): return signal.pthread_sigmask(signal.SIG_BLOCK, [])

# The fault handler timeout thread masks all signals. If the main # thread masks also SIGUSR1, all threads mask this signal. In this # case, if we send SIGUSR1 to the process, the signal is pending in the # main or the faulthandler timeout thread. Unblock SIGUSR1 in the main # thread calls the signal handler only if the signal is pending for the

+

+

+

+

+

+

+

+

+

+

+

+

# Install our signal handler old_handler = signal.signal(signum, self.handler) @@ -537,13 +612,13 @@ class PendingSignalsTests(unittest.TestC old_mask = signal.pthread_sigmask(signal.SIG_UNBLOCK, [signum]) self.addCleanup(signal.pthread_sigmask, signal.SIG_SETMASK, old_mask) with self.assertRaises(ZeroDivisionError):

# Block and then raise SIGUSR1. The signal is blocked: the signal # handler is not called, and the signal is now pending signal.pthread_sigmask(signal.SIG_BLOCK, [signum])

# Check the new mask blocked = self.read_sigmask() @@ -551,14 +626,14 @@ class PendingSignalsTests(unittest.TestC self.assertEqual(old_mask ^ blocked, {signum}) # Unblock SIGUSR1

# Check the new mask unblocked = self.read_sigmask() @@ -570,7 +645,7 @@ class PendingSignalsTests(unittest.TestC def test_main(): try:

--- a/Misc/NEWS +++ b/Misc/NEWS @@ -140,6 +140,9 @@ Core and Builtins Library ------- +- Issue #8407: Add pthread_kill(), sigpending() and sigwait() functions to the

--- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c @@ -503,7 +503,7 @@ PyDoc_STRVAR(getitimer_doc, Returns current value of given itimer."); #endif -#ifdef PYPTHREAD_SIGMASK +#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGWAIT) /* Convert an iterable to a sigset. Return 0 on success, return -1 and raise an exception on error. / @@ -551,7 +551,9 @@ error: Py_XDECREF(iterator); return result; } +#endif +#if defined(PYPTHREAD_SIGMASK) || defined(HAVE_SIGPENDING) static PyObject sigset_to_set(sigset_t mask) { @@ -585,7 +587,9 @@ sigset_to_set(sigset_t mask) } return result; } +#endif +#ifdef PYPTHREAD_SIGMASK static PyObject * signal_pthread_sigmask(PyObject *self, PyObject *args) { @@ -603,7 +607,7 @@ signal_pthread_sigmask(PyObject *self, P err = pthread_sigmask(how, &mask, &previous); if (err != 0) { errno = err;

#endif /* #ifdef PYPTHREAD_SIGMASK */ +#ifdef HAVE_SIGPENDING +static PyObject * +signal_sigpending(PyObject *self) +{

+} + +PyDoc_STRVAR(signal_sigpending_doc, +"sigpending() -> list\n[](#l6.58) +\n[](#l6.59) +Examine pending signals."); +#endif /* #ifdef HAVE_SIGPENDING */ + + +#ifdef HAVE_SIGWAIT +static PyObject * +signal_sigwait(PyObject *self, PyObject *args) +{

+

+

+

+

+} + +PyDoc_STRVAR(signal_sigwait_doc, +"sigwait(sigset) -> signum\n[](#l6.88) +\n[](#l6.89) +Wait a signal."); +#endif /* #ifdef HAVE_SIGPENDING */ + + +#if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) +static PyObject * +signal_pthread_kill(PyObject *self, PyObject *args) +{

+

+

+

+

+} + +PyDoc_STRVAR(signal_pthread_kill_doc, +"pthread_kill(thread_id, signum)\n[](#l6.120) +\n[](#l6.121) +Send a signal to a thread."); +#endif /* #if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD) / + + + / List of functions defined in the module */ static PyMethodDef signal_methods[] = { #ifdef HAVE_ALARM @@ -644,10 +730,22 @@ static PyMethodDef signal_methods[] = { #endif {"default_int_handler", signal_default_int_handler, METH_VARARGS, default_int_handler_doc}, +#if defined(HAVE_PTHREAD_KILL) && defined(WITH_THREAD)

+#endif #ifdef PYPTHREAD_SIGMASK {"pthread_sigmask", (PyCFunction)signal_pthread_sigmask, METH_VARARGS, signal_pthread_sigmask_doc}, #endif +#ifdef HAVE_SIGPENDING

+#endif +#ifdef HAVE_SIGWAIT

+#endif {NULL, NULL} /* sentinel */ };

--- a/configure +++ b/configure @@ -9258,11 +9258,12 @@ for ac_func in alarm accept4 setitimer g initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mbrtowc mkdirat mkfifo [](#l7.4) mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll [](#l7.5) posix_fallocate posix_fadvise pread [](#l7.6)

--- a/configure.in +++ b/configure.in @@ -2503,11 +2503,12 @@ AC_CHECK_FUNCS(alarm accept4 setitimer g initgroups kill killpg lchmod lchown lockf linkat lstat lutimes mbrtowc mkdirat mkfifo [](#l8.4) mkfifoat mknod mknodat mktime mremap nice openat pathconf pause plock poll [](#l8.5) posix_fallocate posix_fadvise pread [](#l8.6)

--- a/pyconfig.h.in +++ b/pyconfig.h.in @@ -590,6 +590,9 @@ /* Define to 1 if you have the pthread_sigmask' function. */[](#l9.4) #undef HAVE_PTHREAD_SIGMASK[](#l9.5) [](#l9.6) +/* Define to 1 if you have the pthread_kill' function. / +#undef HAVE_PTHREAD_KILL + / Define to 1 if you have the <pty.h> header file. / #undef HAVE_PTY_H @@ -719,12 +722,18 @@ / Define to 1 if you have the siginterrupt' function. */[](#l9.14) #undef HAVE_SIGINTERRUPT[](#l9.15) [](#l9.16) +/* Define to 1 if you have the sigpending' function. / +#undef HAVE_SIGPENDING + / Define to 1 if you have the <signal.h> header file. / #undef HAVE_SIGNAL_H / Define to 1 if you have the sigrelse' function. */[](#l9.23) #undef HAVE_SIGRELSE[](#l9.24) [](#l9.25) +/* Define to 1 if you have the sigwait' function. / +#undef HAVE_SIGWAIT + / Define to 1 if you have the `snprintf' function. */ #undef HAVE_SNPRINTF