Harden the Unix signals code to be more async signal safe.
authorChandler Carruth <chandlerc@gmail.com>
Sat, 16 Jun 2012 00:09:41 +0000 (00:09 +0000)
committerChandler Carruth <chandlerc@gmail.com>
Sat, 16 Jun 2012 00:09:41 +0000 (00:09 +0000)
commit0b8b3ba21ee7c1a16ac844965dbace820b263bc0
tree4c7caff6f6d792c7acba5a062a1760d635909f0e
parentaf06825460e1905a7739386c28253c13e3653394
Harden the Unix signals code to be more async signal safe.

This is likely only the tip of the ice berg, but this particular bug
caused any double-free on a glibc system to turn into a deadlock! It is
not generally safe to either allocate or release heap memory from within
the signal handler. The 'pop_back()' in RemoveFilesToRemove was deleting
memory and causing the deadlock. What's worse, eraseFromDisk in PathV1
has lots of allocation and deallocation paths. We even passed 'true' in
a place that would have caused the *signal handler* to try to run the
'system' system call and shell out to 'rm -rf'. That was never going to
work...

This patch switches the file removal to use a vector of strings so that
the exact text needed for the 'unlink' system call can be stored there.
It switches the loop to be a boring indexed loop, and directly calls
unlink without looking at the error. It also works quite hard to ensure
that calling 'c_str()' is safe, by ensuring that the non-signal-handling
code path that manipulates the vector always leaves it in a state where
every element has already had 'c_str()' called at least once.

I dunno exactly how overkill this is, but it fixes the
deadlock-on-double free issue, and seems likely to prevent any other
issues from sneaking up.

Sorry for not having a test case, but I *really* don't know how to test
signal handling code easily....

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@158580 91177308-0d34-0410-b5e6-96231b3b80d8
lib/Support/Unix/Signals.inc