[Python-Dev] uuid creation not thread-safe?

Guido van Rossum guido at python.org
Fri Aug 24 07:03:57 CEST 2007


This was now fixed in 3.0. Somebody might want to backport.

On 7/28/07, lcaamano <lcaamano at gmail.com> wrote:
>
> On Jul 20, 1:52 pm, "Guido van Rossum" <gu... at python.org> wrote:
> > I discovered what appears to be a thread-unsafety inuuid.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)
> >         returnUUID(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?
> >
>
>
> 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
>
>


-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-Dev mailing list