# HG changeset patch # User Charles-François Natali # Date 1455316761 0 # Node ID d3662c088db8fb2c89f754031f18b1543419fed9 # Parent 5715a6d9ff12053e81f7ad75268ac059b079b351 Issue #24303: Fix random EEXIST upon multiprocessing semaphores creation with Linux PID namespaces enabled. diff --git a/Modules/_multiprocessing/semaphore.c b/Modules/_multiprocessing/semaphore.c --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -429,7 +429,7 @@ semlock_new(PyTypeObject *type, PyObject 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 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;