rust/src/libstd/sys_common
Alex Crichton 495c998508 std: Avoid locks during TLS destruction on Windows
Gecko recently had a bug reported [1] with a deadlock in the Rust TLS
implementation for Windows. TLS destructors are implemented in a sort of ad-hoc
fashion on Windows as it doesn't natively support destructors for TLS keys. To
work around this the runtime manages a list of TLS destructors and registers a
hook to get run whenever a thread exits. When a thread exits it takes a look at
the list and runs all destructors.

Unfortunately it turns out that there's a lock which is held when our "at thread
exit" callback is run. The callback then attempts to acquire a lock protecting
the list of TLS destructors. Elsewhere in the codebase while we hold a lock over
the TLS destructors we try to acquire the same lock held first before our
special callback is run. And as a result, deadlock!

This commit sidesteps the issue with a few small refactorings:

* Removed support for destroying a TLS key on Windows. We don't actually ever
  exercise this as a public-facing API, and it's only used during `lazy_init`
  during racy situations. To handle that we just synchronize `lazy_init`
  globally on Windows so we never have to call `destroy`.

* With no need to support removal the global synchronized `Vec` was tranformed
  to a lock-free linked list. With the removal of locks this means that
  iteration no long requires a lock and as such we won't run into the deadlock
  problem mentioned above.

Note that it's still a general problem that you have to be extra super careful
in TLS destructors. For example no code which runs a TLS destructor on Windows
can call back into the Windows API to do a dynamic library lookup. Unfortunately
I don't know of a great way around that, but this at least fixes the immediate
problem that Gecko was seeing which is that with "well behaved" destructors the
system would still deadlock!

[1]: https://bugzilla.mozilla.org/show_bug.cgi?id=1358151
2017-05-05 06:59:49 -07:00
..
gnu travis: Fuchsia builder 2017-03-10 08:28:40 -08:00
at_exit_imp.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
backtrace.rs std: Back out backtrace pruning logic 2017-04-18 06:49:39 -07:00
condvar.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
io.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
memchr.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
mod.rs std: Remove cfg(cargobuild) annotations 2017-02-06 08:42:54 -08:00
mutex.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
net.rs Fix libc::bind call on aarch64-linux-android 2017-03-25 11:03:06 -03:00
poison.rs Adding links around Sender/SyncSender/Receiver errors; Adding more documentation to channel() and sync_channel(); adding more links #29377 2017-04-08 15:33:21 -04:00
remutex.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
rwlock.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
thread.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
thread_info.rs std: remove a workaround for privacy limitations that isn't necessary anymore 2017-03-13 18:42:23 -07:00
thread_local.rs std: Avoid locks during TLS destruction on Windows 2017-05-05 06:59:49 -07:00
util.rs std: Move sys_common to libstd/sys_common 2016-11-01 17:08:24 +00:00
wtf8.rs Auto merge of #40009 - clarcharr:box_to_buf, r=alexcrichton 2017-03-15 04:24:10 +00:00