]> granicus.if.org Git - python/commitdiff
signal: add strsignal() (#6017)
authorAntoine Pietri <antoine.pietri1@gmail.com>
Mon, 12 Mar 2018 13:42:34 +0000 (14:42 +0100)
committerAntoine Pitrou <pitrou@free.fr>
Mon, 12 Mar 2018 13:42:34 +0000 (14:42 +0100)
Co-authored-by: Vajrasky Kok <sky.kok@speaklikeaking.com>
Doc/library/signal.rst
Lib/test/test_signal.py
Misc/NEWS.d/next/Library/2018-03-07-19-37-00.bpo-22674.2sIMmM.rst [new file with mode: 0644]
Modules/clinic/signalmodule.c.h
Modules/signalmodule.c

index 67eaa2c6381376137ea09c353c0d3fa0dc83b72e..3f17e08f0f959983d321d7f91dc6bd75d562ab96 100644 (file)
@@ -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
index 48b7a392e50b34fa14ec413cfd14f1dad345a6db..fbb12a5b67bfcac310b48db9c936bb04d22dc022 100644 (file)
@@ -43,6 +43,8 @@ class PosixTests(unittest.TestCase):
         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)
@@ -55,6 +57,10 @@ class PosixTests(unittest.TestCase):
         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__)
diff --git a/Misc/NEWS.d/next/Library/2018-03-07-19-37-00.bpo-22674.2sIMmM.rst b/Misc/NEWS.d/next/Library/2018-03-07-19-37-00.bpo-22674.2sIMmM.rst
new file mode 100644 (file)
index 0000000..a9af5da
--- /dev/null
@@ -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).
index dc3aadf878b2f26e47a5e0cc254985bf77f6b59d..1c439716c4988033d88173b9c30b8c3b87caa7b4 100644 (file)
@@ -129,6 +129,36 @@ exit:
     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__,
@@ -440,4 +470,4 @@ exit:
 #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]*/
index b553eedc0f2c3e8a9f4a2d63cf3098f82a090cd0..7916160143840c59eefcfb01a408a33baa125283 100644 (file)
@@ -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]
@@ -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