Author ncoghlan
Recipients jab, jrus, ncoghlan, r.david.murray, santagada
Date 2009-10-10.13:24:48
SpamBayes Score 3.14461e-11
Marked as misclassified No
Message-id <1255181091.27.0.310009136208.issue6763@psf.upfronthosting.co.za>
In-reply-to
Content
The thread safety problem comes from the fact that performing file IO as
mimetypes.init() does will release the GIL - if you want to ensure
thread safety in that context, you have to do your own locking.
mimetypes ignore this thread syncrhonisation problem completely with
unhelpful results.

An attempt was made to address the race condition in r72045 by
eliminating the infinite recursion. Instead, you just get init() being
invoked multiple times on different MimeTypes instances, with the last
one "winning" and being kept as the _db module global (which does
eliminate the crash, but has problems of its own).

This crash probably involves hitting the recursion limit and that's
always a bit dicey as to whether we actually manage to trap it before
the C stack goes boom. With this case being an infinite recursion in an
__init__() method leading to an infinite number of a given object type
being allocated, that's a bit special since it raises the prospect of
potentially running out of heap memory (although that's unlikely with
the default recursion limit unless there are an awful lot of threads
involved).

To check the simple failure mechnism, I tried threading out the following:

class Broken():
  def __init__(self):
    break_it()

def break_it():
  Broken()

from threading import Thread
threads = [Thread(target=break_it) for x in range(100)]
for t in threads: t.start()

On my machine, the threads fail with "RuntimeError: maximum recursion
depth exceeded" for a recursion limit of 1000 or 10000, but segfault at
100,000. However, the 100k recursion limit segfaults even if I only use
a single thread (i.e. call break_it() directly without involving the
threading module at all).

For the OP:

What value do you get for sys.getrecursionlimit()?
Do you still get the segfault if you use sys.setrecursionlimit() to
lower the maximum allowed level of recursion? (e.g. limit it to 200 or
500 recursions)
History
Date User Action Args
2009-10-10 13:24:51ncoghlansetrecipients: + ncoghlan, r.david.murray, jab, jrus, santagada
2009-10-10 13:24:51ncoghlansetmessageid: <1255181091.27.0.310009136208.issue6763@psf.upfronthosting.co.za>
2009-10-10 13:24:49ncoghlanlinkissue6763 messages
2009-10-10 13:24:48ncoghlancreate