Fix a ThreadLocal bug: hold the meta lock when resizing the element vector
authorJordan DeLong <jdelong@fb.com>
Thu, 15 Aug 2013 00:03:04 +0000 (17:03 -0700)
committerSara Golemon <sgolemon@fb.com>
Wed, 28 Aug 2013 21:30:11 +0000 (14:30 -0700)
commitc55ca702ba15bc9dbb7f5c18b267e97ec1d79073
tree2aa9b9d08d18e4efa03d78b605fa29950c9ac89d
parent21effa23799fe52594ef73baffd3f2c8a6e8b43f
Fix a ThreadLocal bug: hold the meta lock when resizing the element vector

Summary:
There appears to be a race here.  leizha reported issues with
a heavily recycled AtomicHashMap (ThreadCachedInt inside).  It looks
like what's happening is this:

- Thread A: ~ThreadCachedInt from an AHM
- meta lock is taken, and the ThreadElement list is iterated
- all entries are zerod, and the id is marked free
- then releases the lock
- Thread B: someone is calling get() on an unrelated id
- hit reserve: rallocm on the pointer or unsynchronized memcpy from
the element vector
- waits on the lock
- when it gets the lock, it stores back the value that it read that
was zero'd by A.

Later, someone reuses the id from the freelist, and reuses the
previously freed pointer, and eventually double-freeing it.  (nullptr
is the signifier for "this thread doesn't have an instance of the
threadlocal yet").

Test Plan:
leizha's test case doesn't segv after this diff---it was
reliably breaking with corruption in malloc before it.  I'm working on
making that test case into a unit test to add to this diff, but I'm
putting it up early in case there's something wrong with the theory
above or in case someone has an idea for a better fix.

Reviewed By: tudorb@fb.com

FB internal diff: D928534
folly/detail/ThreadLocalDetail.h
folly/test/AHMIntStressTest.cpp [new file with mode: 0644]