Fixed a very unlikely race condition in WTF::WordLock
authorggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 29 Apr 2018 15:23:52 +0000 (15:23 +0000)
committerggaren@apple.com <ggaren@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 29 Apr 2018 15:23:52 +0000 (15:23 +0000)
commitb42f8ca2b667322ae2e3bcbd24cf1c43ef60f5df
tree5aed09506e8726e9a4a15e36dbcb96f77d848b0c
parentb24077e0714b69a45afbcaad9289da56ce780aec
Fixed a very unlikely race condition in WTF::WordLock
https://bugs.webkit.org/show_bug.cgi?id=185117

Reviewed by Saam Barati.

The race goes like this:

Thread L is in lockSlowCase() and thread U is in unlockSlowCase();

- U acquires queueHead->parkingLock.
- U sets queueHead->shouldPark = false
- U releases queueHead->parkingLock.
- L spuriously wakes up from queueHead->parkingLock.wait()
- L acquires queueHead->parkingLock.
- L notices that queueHead->shouldPark = false, and acquires the WordLock
- L finishes all its work and exits, freeing queueHead
- U notifies queueHead->parkingLock (after free) and crashes or deadlocks

These conditions are currently so unlikely that I don't know how to test
them. I noticed this race because I changed WordLock's allocation pattern
to allow queueHead to be freed more often, and I crashed / deadlocked 100%.

Shout out to <http://en.cppreference.com/w/cpp/thread/condition_variable/notify_one>
for explaining this.

* benchmarks/ToyLocks.h: Fixed build.

* wtf/WordLock.cpp:
(WTF::WordLock::unlockSlow): Hold the lock a little longer to avoid
this race.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@231148 268f45cc-cd09-0410-ab3c-d52691b4dbfc
Source/WTF/ChangeLog
Source/WTF/benchmarks/ToyLocks.h
Source/WTF/wtf/WordLock.cpp