Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
signal: add strsignal() (#6017)
Co-authored-by: Vajrasky Kok <sky.kok@speaklikeaking.com>
  • Loading branch information
2 people authored and pitrou committed Mar 12, 2018
1 parent 4484f9d commit 5d2a27d
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 1 deletion.
9 changes: 9 additions & 0 deletions Doc/library/signal.rst
Expand Up @@ -207,6 +207,15 @@ The :mod:`signal` module defines the following functions:
installed from Python.


.. function:: strsignal(signalnum)

Return the system description of the signal *signalnum*, such as
"Interrupt", "Segmentation fault", etc. Returns :const:`None` if the signal
is not recognized.

.. versionadded:: 3.8


.. function:: pause()

Cause the process to sleep until a signal is received; the appropriate handler
Expand Down
6 changes: 6 additions & 0 deletions Lib/test/test_signal.py
Expand Up @@ -43,6 +43,8 @@ def test_out_of_range_signal_number_raises_error(self):
self.assertRaises(ValueError, signal.signal, 4242,
self.trivial_signal_handler)

self.assertRaises(ValueError, signal.strsignal, 4242)

def test_setting_signal_handler_to_none_raises_error(self):
self.assertRaises(TypeError, signal.signal,
signal.SIGUSR1, None)
Expand All @@ -55,6 +57,10 @@ def test_getsignal(self):
signal.signal(signal.SIGHUP, hup)
self.assertEqual(signal.getsignal(signal.SIGHUP), hup)

def test_strsignal(self):
self.assertEqual(signal.strsignal(signal.SIGINT), "Interrupt")
self.assertEqual(signal.strsignal(signal.SIGTERM), "Terminated")

# Issue 3864, unknown if this affects earlier versions of freebsd also
def test_interprocess_signal(self):
dirname = os.path.dirname(__file__)
Expand Down
@@ -0,0 +1,2 @@
Add the strsignal() function in the signal module that returns the system
description of the given signal, as returned by strsignal(3).
32 changes: 31 additions & 1 deletion Modules/clinic/signalmodule.c.h
Expand Up @@ -129,6 +129,36 @@ signal_getsignal(PyObject *module, PyObject *arg)
return return_value;
}

PyDoc_STRVAR(signal_strsignal__doc__,
"strsignal($module, signalnum, /)\n"
"--\n"
"\n"
"Return the system description of the given signal.\n"
"\n"
"The return values can be such as \"Interrupt\", \"Segmentation fault\", etc.\n"
"Returns None if the signal is not recognized.");

#define SIGNAL_STRSIGNAL_METHODDEF \
{"strsignal", (PyCFunction)signal_strsignal, METH_O, signal_strsignal__doc__},

static PyObject *
signal_strsignal_impl(PyObject *module, int signalnum);

static PyObject *
signal_strsignal(PyObject *module, PyObject *arg)
{
PyObject *return_value = NULL;
int signalnum;

if (!PyArg_Parse(arg, "i:strsignal", &signalnum)) {
goto exit;
}
return_value = signal_strsignal_impl(module, signalnum);

exit:
return return_value;
}

#if defined(HAVE_SIGINTERRUPT)

PyDoc_STRVAR(signal_siginterrupt__doc__,
Expand Down Expand Up @@ -440,4 +470,4 @@ signal_pthread_kill(PyObject *module, PyObject *const *args, Py_ssize_t nargs)
#ifndef SIGNAL_PTHREAD_KILL_METHODDEF
#define SIGNAL_PTHREAD_KILL_METHODDEF
#endif /* !defined(SIGNAL_PTHREAD_KILL_METHODDEF) */
/*[clinic end generated code: output=36132f4189381fe0 input=a9049054013a1b77]*/
/*[clinic end generated code: output=7b41486acf93aa8e input=a9049054013a1b77]*/
61 changes: 61 additions & 0 deletions Modules/signalmodule.c
Expand Up @@ -504,6 +504,66 @@ signal_getsignal_impl(PyObject *module, int signalnum)
}
}


/*[clinic input]
signal.strsignal
signalnum: int
/
Return the system description of the given signal.
The return values can be such as "Interrupt", "Segmentation fault", etc.
Returns None if the signal is not recognized.
[clinic start generated code]*/

static PyObject *
signal_strsignal_impl(PyObject *module, int signalnum)
/*[clinic end generated code: output=44e12e1e3b666261 input=b77914b03f856c74]*/
{
char *res;

if (signalnum < 1 || signalnum >= NSIG) {
PyErr_SetString(PyExc_ValueError,
"signal number out of range");
return NULL;
}

#ifdef MS_WINDOWS
/* Custom redefinition of POSIX signals allowed on Windows */
switch (signalnum) {
case SIGINT:
res = "Interrupt";
break;
case SIGILL:
res = "Illegal instruction";
break;
case SIGABRT:
res = "Aborted";
break;
case SIGFPE:
res = "Floating point exception";
break;
case SIGSEGV:
res = "Segmentation fault";
break;
case SIGTERM:
res = "Terminated";
break;
default:
Py_RETURN_NONE;
}
#else
errno = 0;
res = strsignal(signalnum);

if (errno || res == NULL || strstr(res, "Unknown signal") != NULL)
Py_RETURN_NONE;
#endif

return Py_BuildValue("s", res);
}

#ifdef HAVE_SIGINTERRUPT

/*[clinic input]
Expand Down Expand Up @@ -1152,6 +1212,7 @@ static PyMethodDef signal_methods[] = {
SIGNAL_SETITIMER_METHODDEF
SIGNAL_GETITIMER_METHODDEF
SIGNAL_SIGNAL_METHODDEF
SIGNAL_STRSIGNAL_METHODDEF
SIGNAL_GETSIGNAL_METHODDEF
{"set_wakeup_fd", (PyCFunction)signal_set_wakeup_fd, METH_VARARGS | METH_KEYWORDS, set_wakeup_fd_doc},
SIGNAL_SIGINTERRUPT_METHODDEF
Expand Down

0 comments on commit 5d2a27d

Please sign in to comment.