Fix for semaphores in pid namespaces http://bugs.python.org/issue24303 --- a/Modules/_multiprocessing/semaphore.c +++ b/Modules/_multiprocessing/semaphore.c @@ -7,6 +7,7 @@ */ #include "multiprocessing.h" +#include enum { RECURSIVE_MUTEX, SEMAPHORE }; @@ -419,7 +420,7 @@ semlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { char buffer[256]; SEM_HANDLE handle = SEM_FAILED; - int kind, maxvalue, value; + int kind, maxvalue, value, try; PyObject *result; static char *kwlist[] = {"kind", "value", "maxvalue", NULL}; static int counter = 0; @@ -433,10 +434,24 @@ semlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return NULL; } - PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%d", (long)getpid(), counter++); + /* With pid namespaces, we may have multiple processes with the same pid. + * Instead of relying on the pid to be unique, we use the microseconds time + * to attempt to a unique filename. */ + for (try = 0; try < 100; ++try) { + struct timespec tv; + long arbitrary = clock_gettime(CLOCK_REALTIME, &tv) ? 0 : tv.tv_nsec; + PyOS_snprintf(buffer, sizeof(buffer), "/mp%ld-%d-%ld", + (long)getpid(), + counter++, + arbitrary); + SEM_CLEAR_ERROR(); + handle = SEM_CREATE(buffer, value, maxvalue); + if (handle != SEM_FAILED) + break; + else if (errno != EEXIST) + goto failure; + } - 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;