Skip to content

Commit bec78f6

Browse files
committed
Unlock BEFORE resuming the waitAll waiting task, to avoid unlock() on
released memory. Because the waitAll() group method is called before the group returns from withTaskGroup and is used to ensure all tasks have completed before we destroy the task group, this method is then immediately followed by calling TaskGroup::destroy. If we, as previously, first resume the waiting task and then attempt to unlock the lock held by the group, we are in an unsafe situation with racing the task group destroy() and the unlock(). Therefore, we must release the lock before we resume the waiting task.
1 parent 62461e4 commit bec78f6

File tree

1 file changed

+5
-2
lines changed

1 file changed

+5
-2
lines changed

stdlib/public/Concurrency/TaskGroup.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1810,9 +1810,12 @@ void TaskGroupBase::waitAll(SwiftError* bodyError, AsyncTask *waitingTask,
18101810
swift_release(completedTask);
18111811
}
18121812

1813-
waitingTask->runInFullyEstablishedContext();
1814-
1813+
// We MUST release the lock before we resume the waiting task, because the resumption
1814+
// will allow it to destroy the task group, in which case the unlock()
1815+
// would be performed on freed memory (!)
18151816
unlock();
1817+
1818+
waitingTask->runInFullyEstablishedContext();
18161819
return;
18171820
}
18181821

0 commit comments

Comments
 (0)