<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Jul 18, 2016 at 1:39 PM, Bruno Cardoso Lopes via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
C++ static destructors can be problematic in multi-threaded<br>
environment. Some of the issues users often complain about include:<br>
1. Teardown ordering: crashes when one thread is exiting the process<br>
and calling destructors while another thread is still running and<br>
accessing the destructing variables<br>
2. Shared code that is compiled both as an application and as a<br>
library. When library mode is chosen, goto (1).<br>
3. Some projects currently override __cxa_atexit to avoid the behavior<br>
in question.<br>
<br>
To get around that, I propose we add a compiler option (e.g.<br>
-fno-cxx-static-destructors) to allow clang to suppress destructor<br>
registration (currently done via __cxa_atexit, atexit):<br>
<a href="https://reviews.llvm.org/D22474" rel="noreferrer" target="_blank">https://reviews.llvm.org/D22474</a><br>
<br>
I'm opening this discussion here on cfe-dev to get some feedback on the matter<br>
<br>
One can argue that dealing with C++ static destructors in<br>
multi-threaded environment is solely the responsibility of the<br>
developer, however since (AFAIK) we don't have any standard guaranteed<br>
semantic for "global destruction vs. threads", it seems fair to me<br>
that we could give developers some option.</blockquote><div><br></div><div>They already have options. They can use std::quick_exit, which was added specifically to address this problem, if they don't want destructors to be run at all. There are standard techniques to avoid destructors being run for specific objects:</div><div><br></div><div>  template<typename T> union not_destroyed {</div><div>    T value;</div><div>    template<typename ...U> constexpr not_destroyed(U &&...u) : value(std::forward<U>(u)...) {}</div><div>    ~not_destroyed() {} </div><div>  };</div><div>  not_destroyed<std::string> my_str("foo"); // technically has object lifetime issues</div><div><br></div><div>  ... or ...</div><div><br></div><div>  std::string &&s = *new std::string("foo");</div><div><br></div><div>Are these options not good enough? Is per-TU control (with no source changes) a goal here, or is it more of an incidental property of the solution? It seems to me that we should prefer to either push people towards the standard std::quick_exit solution or propose an alternative standard mechanism rather than invent our own proprietary way to work around this problem.</div></div></div></div>