]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39511: Fix multiprocessing semlock_acquire() (GH-18298)
authorVictor Stinner <vstinner@python.org>
Sat, 1 Feb 2020 00:25:59 +0000 (01:25 +0100)
committerGitHub <noreply@github.com>
Sat, 1 Feb 2020 00:25:59 +0000 (01:25 +0100)
The Python C API must not be used when the GIL is released: only
access Py_None when the GIL is hold.

Modules/_multiprocessing/semaphore.c

index 4be2deae377504bf2e2f7fbba95c1504eb74356a..ee490256d2a27e1ef3f2b3458a847af55f69c680 100644 (file)
@@ -268,11 +268,8 @@ static PyObject *
 semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
 {
     int blocking = 1, res, err = 0;
-    double timeout;
     PyObject *timeout_obj = Py_None;
     struct timespec deadline = {0};
-    struct timeval now;
-    long sec, nsec;
 
     static char *kwlist[] = {"block", "timeout", NULL};
 
@@ -285,19 +282,23 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
         Py_RETURN_TRUE;
     }
 
-    if (timeout_obj != Py_None) {
-        timeout = PyFloat_AsDouble(timeout_obj);
-        if (PyErr_Occurred())
+    int use_deadline = (timeout_obj != Py_None);
+    if (use_deadline) {
+        double timeout = PyFloat_AsDouble(timeout_obj);
+        if (PyErr_Occurred()) {
             return NULL;
-        if (timeout < 0.0)
+        }
+        if (timeout < 0.0) {
             timeout = 0.0;
+        }
 
+        struct timeval now;
         if (gettimeofday(&now, NULL) < 0) {
             PyErr_SetFromErrno(PyExc_OSError);
             return NULL;
         }
-        sec = (long) timeout;
-        nsec = (long) (1e9 * (timeout - sec) + 0.5);
+        long sec = (long) timeout;
+        long nsec = (long) (1e9 * (timeout - sec) + 0.5);
         deadline.tv_sec = now.tv_sec + sec;
         deadline.tv_nsec = now.tv_usec * 1000 + nsec;
         deadline.tv_sec += (deadline.tv_nsec / 1000000000);
@@ -315,7 +316,7 @@ semlock_acquire(SemLockObject *self, PyObject *args, PyObject *kwds)
         /* Couldn't acquire immediately, need to block */
         do {
             Py_BEGIN_ALLOW_THREADS
-            if (timeout_obj == Py_None) {
+            if (!use_deadline) {
                 res = sem_wait(self->handle);
             }
             else {