uuid creation not thread-safe?

I discovered what appears to be a thread-unsafety in uuid.py. This is in the trunk as well as in 3.x; I'm using the trunk here for easy reference. There's some code around like 395: import ctypes, ctypes.util _buffer = ctypes.create_string_buffer(16) This creates a *global* buffer which is used as the output parameter to later calls to _uuid_generate_random() and _uuid_generate_time(). For example, around line 481, in uuid1(): _uuid_generate_time(_buffer) return UUID(bytes=_buffer.raw) Clearly if two threads do this simultaneously they are overwriting _buffer in unpredictable order. There are a few other occurrences of this too. I find it somewhat disturbing that what seems a fairly innocent function that doesn't *appear* to have global state is nevertheless not thread-safe. Would it be wise to fix this, e.g. by allocating a fresh output buffer inside uuid1() and other callers? -- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Jul 20, 1:52 pm, "Guido van Rossum" <gu...@python.org> wrote:
I didn't find any reply to this, which is odd, so forgive me if it's old news. I agree with you that it's not thread safe and that a local buffer in the stack should fix it. Just for reference, the thread-safe uuid extension we've been using since python 2.1, which I don't recall where we borrow it from, uses a local buffer in the stack. It looks like this: -----begin uuid.c-------------- static char uuid__doc__ [] = "DCE compatible Universally Unique Identifier module"; #include "Python.h" #include <uuid/uuid.h> static char uuidgen__doc__ [] = "Create a new DCE compatible UUID value"; static PyObject * uuidgen(void) { uuid_t out; char buf[48]; uuid_generate(out); uuid_unparse(out, buf); return PyString_FromString(buf); } static PyMethodDef uuid_methods[] = { {"uuidgen", uuidgen, 0, uuidgen__doc__}, {NULL, NULL} /* Sentinel */ }; DL_EXPORT(void) inituuid(void) { Py_InitModule4("uuid", uuid_methods, uuid__doc__, (PyObject *)NULL, PYTHON_API_VERSION); } -----end uuid.c-------------- It also seems that using uuid_generate()/uuid_unparse() should be faster than using uuid_generate_random() and then creating a python object to call its __str__ method. If so, it would be nice if the uuid.py module also provided equivalent fast versions that returned strings instead of objects. -- Luis P Caamano Atlanta, GA, USA

This was now fixed in 3.0. Somebody might want to backport. On 7/28/07, lcaamano <lcaamano@gmail.com> wrote:
-- --Guido van Rossum (home page: http://www.python.org/~guido/)

On Jul 20, 1:52 pm, "Guido van Rossum" <gu...@python.org> wrote:
I didn't find any reply to this, which is odd, so forgive me if it's old news. I agree with you that it's not thread safe and that a local buffer in the stack should fix it. Just for reference, the thread-safe uuid extension we've been using since python 2.1, which I don't recall where we borrow it from, uses a local buffer in the stack. It looks like this: -----begin uuid.c-------------- static char uuid__doc__ [] = "DCE compatible Universally Unique Identifier module"; #include "Python.h" #include <uuid/uuid.h> static char uuidgen__doc__ [] = "Create a new DCE compatible UUID value"; static PyObject * uuidgen(void) { uuid_t out; char buf[48]; uuid_generate(out); uuid_unparse(out, buf); return PyString_FromString(buf); } static PyMethodDef uuid_methods[] = { {"uuidgen", uuidgen, 0, uuidgen__doc__}, {NULL, NULL} /* Sentinel */ }; DL_EXPORT(void) inituuid(void) { Py_InitModule4("uuid", uuid_methods, uuid__doc__, (PyObject *)NULL, PYTHON_API_VERSION); } -----end uuid.c-------------- It also seems that using uuid_generate()/uuid_unparse() should be faster than using uuid_generate_random() and then creating a python object to call its __str__ method. If so, it would be nice if the uuid.py module also provided equivalent fast versions that returned strings instead of objects. -- Luis P Caamano Atlanta, GA, USA

This was now fixed in 3.0. Somebody might want to backport. On 7/28/07, lcaamano <lcaamano@gmail.com> wrote:
-- --Guido van Rossum (home page: http://www.python.org/~guido/)
participants (2)
-
Guido van Rossum
-
lcaamano