Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-22674: signal: add strsignal() #6017

Merged
merged 1 commit into from
Mar 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Doc/library/signal.rst
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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