diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2015-04-13 17:48:19 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2015-04-13 17:48:19 (GMT) |
commit | cb46f0ecb05ef3ccd3f53ced7f60748c0b3c710a (patch) | |
tree | bd7bf53350b0acbd12721bcfba898d6f6072fc1c /Modules/_io/bufferedio.c | |
parent | 9c680b07285867844927871ddcbf60c93e786e1f (diff) | |
parent | 25f85d4bd58d86d3e6ce99cb9f270e96bf5ba08f (diff) | |
download | cpython-cb46f0ecb05ef3ccd3f53ced7f60748c0b3c710a.zip cpython-cb46f0ecb05ef3ccd3f53ced7f60748c0b3c710a.tar.gz cpython-cb46f0ecb05ef3ccd3f53ced7f60748c0b3c710a.tar.bz2 |
Issue #23309: Avoid a deadlock at shutdown if a daemon thread is aborted
while it is holding a lock to a buffered I/O object, and the main thread
tries to use the same I/O object (typically stdout or stderr). A fatal
error is emitted instead.
Diffstat (limited to 'Modules/_io/bufferedio.c')
-rw-r--r-- | Modules/_io/bufferedio.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/Modules/_io/bufferedio.c b/Modules/_io/bufferedio.c index ea9f533..7cf5dda 100644 --- a/Modules/_io/bufferedio.c +++ b/Modules/_io/bufferedio.c @@ -318,14 +318,35 @@ typedef struct { static int _enter_buffered_busy(buffered *self) { + int relax_locking; + PyLockStatus st; if (self->owner == PyThread_get_thread_ident()) { PyErr_Format(PyExc_RuntimeError, "reentrant call inside %R", self); return 0; } + relax_locking = (_Py_Finalizing != NULL); Py_BEGIN_ALLOW_THREADS - PyThread_acquire_lock(self->lock, 1); + if (!relax_locking) + st = PyThread_acquire_lock(self->lock, 1); + else { + /* When finalizing, we don't want a deadlock to happen with daemon + * threads abruptly shut down while they owned the lock. + * Therefore, only wait for a grace period (1 s.). + * Note that non-daemon threads have already exited here, so this + * shouldn't affect carefully written threaded I/O code. + */ + st = PyThread_acquire_lock_timed(self->lock, 1e6, 0); + } Py_END_ALLOW_THREADS + if (relax_locking && st != PY_LOCK_ACQUIRED) { + PyObject *msgobj = PyUnicode_FromFormat( + "could not acquire lock for %A at interpreter " + "shutdown, possibly due to daemon threads", + (PyObject *) self); + char *msg = PyUnicode_AsUTF8(msgobj); + Py_FatalError(msg); + } return 1; } |