Message 150330 - Python tracker (original) (raw)

IIUC, the deadlock avoidance code just checks that acquiring a per-module lock won't create a cycle. However, I think there's a race, because the cycle detection and the lock acquisition is not atomic.

For example, let's say we have a thread exactly here in in acquire_import_lock(): PyThread_acquire_lock(lock->lock, 1); /* thread inside PyEval_RestoreThread(), waiting for the GIL */ PyEval_RestoreThread(saved); lock->waiters--; } assert(lock->level == 0); lock->tstate = tstate;

It owns the lock, but hasn't yet updated the lock's owner (lock->tstate), so another thread calling detect_circularity() will think that this lock is available, and will proceed, which can eventually lead to a deadlock.

Also, I think that locks will use POSIX semaphores on systems that support only a limited number of them (such as FreeBSD 7), and this might fail in case of nested imports (the infamous ENFILE). I'd have to double check this, though.