diff options
author | Edsko de Vries <edsko@well-typed.com> | 2014-07-13 15:19:39 -0500 |
---|---|---|
committer | Austin Seipp <austin@well-typed.com> | 2014-07-13 15:19:39 -0500 |
commit | 39630ab15cc0607103dc4ef3d9089de44ef17c2d (patch) | |
tree | b3b8171345e7f1876516ef7e237df6d9b55e7890 /rts | |
parent | 1d71e96958cb4374b383e2f254b5358386bf835c (diff) | |
download | haskell-39630ab15cc0607103dc4ef3d9089de44ef17c2d.tar.gz |
Avoid deadlock in freeTask (called by forkProcess)
Summary: Documented in more detail inline with the change.
Test Plan: validate
Reviewers: austin, simonmar, duncan
Reviewed By: austin, simonmar, duncan
Subscribers: simonmar, relrod, carter
Differential Revision: https://phabricator.haskell.org/D59
Diffstat (limited to 'rts')
-rw-r--r-- | rts/Task.c | 14 |
1 files changed, 14 insertions, 0 deletions
diff --git a/rts/Task.c b/rts/Task.c index 12c22c4b02..e191bd0d8c 100644 --- a/rts/Task.c +++ b/rts/Task.c @@ -350,6 +350,20 @@ discardTasksExcept (Task *keep) next = task->all_next; if (task != keep) { debugTrace(DEBUG_sched, "discarding task %" FMT_SizeT "", (size_t)TASK_ID(task)); +#if defined(THREADED_RTS) + // It is possible that some of these tasks are currently blocked + // (in the parent process) either on their condition variable + // `cond` or on their mutex `lock`. If they are we may deadlock + // when `freeTask` attempts to call `closeCondition` or + // `closeMutex` (the behaviour of these functions is documented to + // be undefined in the case that there are threads blocked on + // them). To avoid this, we re-initialize both the condition + // variable and the mutex before calling `freeTask` (we do + // precisely the same for all global locks in `forkProcess`). + initCondition(&task->cond); + initMutex(&task->lock); +#endif + // Note that we do not traceTaskDelete here because // we are not really deleting a task. // The OS threads for all these tasks do not exist in |