]> granicus.if.org Git - python/commitdiff
Issue #24303: Fix random EEXIST upon multiprocessing semaphores creation with
authorCharles-François Natali <cf.natali@gmail.com>
Fri, 12 Feb 2016 22:39:21 +0000 (22:39 +0000)
committerCharles-François Natali <cf.natali@gmail.com>
Fri, 12 Feb 2016 22:39:21 +0000 (22:39 +0000)
Linux PID namespaces enabled.

Misc/NEWS
Modules/_multiprocessing/semaphore.c

index 659d7cada18162ad939b6a8134482694cf45f83a..f8c704f642e99d341d16585cc7287f2c66d9e2f3 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -50,6 +50,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #24303: Fix random EEXIST upon multiprocessing semaphores creation with
+  Linux PID namespaces enabled.
+
 - Issue #25698: Importing module if the stack is too deep no longer replaces
   imported module with the empty one.
 
index b9e8f345fbb1cd70918fb960377dadaea46fd8f3..fc4275434782f998e73c494354c5c5f5d674c900 100644 (file)
@@ -429,7 +429,7 @@ semlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     int kind, maxvalue, value;
     PyObject *result;
     static char *kwlist[] = {"kind", "value", "maxvalue", NULL};
-    static int counter = 0;
+    int try = 0;
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwlist,
                                      &kind, &value, &maxvalue))
@@ -440,10 +440,18 @@ semlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
         return NULL;
     }
 
-    PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%d", (long)getpid(), counter++);
+    /* Create a semaphore with a unique name. The bytes returned by
+     * _PyOS_URandom() are treated as unsigned long to ensure that the filename
+     * is valid (no special characters). */
+    do {
+        unsigned long suffix;
+        _PyOS_URandom((char *)&suffix, sizeof(suffix));
+        PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%lu", (long)getpid(),
+                      suffix);
+        SEM_CLEAR_ERROR();
+        handle = SEM_CREATE(buffer, value, maxvalue);
+    } while ((handle == SEM_FAILED) && (errno == EEXIST) && (++try < 100));
 
-    SEM_CLEAR_ERROR();
-    handle = SEM_CREATE(buffer, value, maxvalue);
     /* On Windows we should fail if GetLastError()==ERROR_ALREADY_EXISTS */
     if (handle == SEM_FAILED || SEM_GET_LAST_ERROR() != 0)
         goto failure;