[llvm] r219638 - Removing the static destructor from ManagedStatic.cpp by controlling the allocation and de-allocation of the mutex.

Chris Bieneman beanz at apple.com
Wed Oct 22 16:07:46 PDT 2014


I have managed to reproduce this and I have a workaround (although it is not ideal). I’ll be sending patches out for review shortly. The root cause of the problem is a bug in Microsoft’s implementation of std::call_once. I found a public bug report tracking the issue here:

http://connect.microsoft.com/VisualStudio/feedbackdetail/view/811192/std-call-once-hangs <http://connect.microsoft.com/VisualStudio/feedbackdetail/view/811192/std-call-once-hangs>

The core issue of the bug is that std::call_once can’t be called from a static initializer. Unfortunately the bug report doesn’t say when or where they fixed it, but I expect it was fixed in a newer version of the C++ runtime. The problem then becomes that I don’t believe LLVM has a precedent for requiring specific versions of the C++ redistributable package (which I think is where the fix would be).

Thanks,
-Chris

> On Oct 17, 2014, at 1:07 PM, Chris Bieneman <cbieneman at apple.com> wrote:
> 
> I’ve been having trouble reproducing this. Admittedly this is probably mostly due to my total lack of familiarity with Windows development. Any help tracking this down is greatly appreciated.
> 
> Thanks,
> -Chris
> 
>> On Oct 14, 2014, at 9:30 AM, Aaron Ballman <aaron at aaronballman.com> wrote:
>> 
>> On Tue, Oct 14, 2014 at 12:28 PM, Chris Bieneman <beanz at apple.com> wrote:
>>> Thank you. I will also see if I can reproduce the hang.
>> 
>> As a data point, I am able to reproduce the hang on Windows 7 with an
>> x86, MSVC-built clang by running the test suite. It is somewhere in
>> the arcmt-test and c-index-test suites, judging by how many tests
>> hung.
>> 
>> ~Aaron
>> 
>>> 
>>> -Chris
>>> 
>>>> On Oct 14, 2014, at 9:11 AM, NAKAMURA Takumi <geek4civic at gmail.com> wrote:
>>>> 
>>>> Excuse me, I have reverted it in r219687.
>>>> 
>>>> It caused hangup in msc builder, probably deadlock in clang's
>>>> arcmt-test and c-index-test.
>>>> http://bb.pgr.jp/builders/ninja-clang-i686-msc17-R/builds/10976
>>>> 
>>>> I will investigate tomorrow.
>>>> 
>>>> 2014-10-14 7:37 GMT+09:00 Chris Bieneman <beanz at apple.com>:
>>>>> Author: cbieneman
>>>>> Date: Mon Oct 13 17:37:25 2014
>>>>> New Revision: 219638
>>>>> 
>>>>> URL: http://llvm.org/viewvc/llvm-project?rev=219638&view=rev
>>>>> Log:
>>>>> Removing the static destructor from ManagedStatic.cpp by controlling the allocation and de-allocation of the mutex.
>>>>> 
>>>>> This patch adds a new llvm_call_once function which is used by the ManagedStatic implementation to safely initialize a global to avoid static construction and destruction.
>>>>> 
>>>>> Modified:
>>>>>  llvm/trunk/include/llvm/Support/Threading.h
>>>>>  llvm/trunk/lib/Support/ManagedStatic.cpp
>>>>> 
>>>>> Modified: llvm/trunk/include/llvm/Support/Threading.h
>>>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Threading.h?rev=219638&r1=219637&r2=219638&view=diff
>>>>> ==============================================================================
>>>>> --- llvm/trunk/include/llvm/Support/Threading.h (original)
>>>>> +++ llvm/trunk/include/llvm/Support/Threading.h Mon Oct 13 17:37:25 2014
>>>>> @@ -15,6 +15,10 @@
>>>>> #ifndef LLVM_SUPPORT_THREADING_H
>>>>> #define LLVM_SUPPORT_THREADING_H
>>>>> 
>>>>> +#if !defined(__MINGW__)
>>>>> +#include <mutex>
>>>>> +#endif
>>>>> +
>>>>> namespace llvm {
>>>>> /// Returns true if LLVM is compiled with support for multi-threading, and
>>>>> /// false otherwise.
>>>>> @@ -33,6 +37,20 @@ namespace llvm {
>>>>> /// the thread stack.
>>>>> void llvm_execute_on_thread(void (*UserFn)(void*), void *UserData,
>>>>>                             unsigned RequestedStackSize = 0);
>>>>> +
>>>>> +template <void (*UserFn)(void)> void llvm_call_once() {
>>>>> +
>>>>> +#if !defined(__MINGW__)
>>>>> +  static std::once_flag flag;
>>>>> +  std::call_once(flag, UserFn);
>>>>> +
>>>>> +#else
>>>>> +  struct InitOnceWrapper {
>>>>> +    InitOnceWrapper() { UserFn(); }
>>>>> +  };
>>>>> +  static InitOnceWrapper InitOnceVar;
>>>>> +#endif
>>>>> +}
>>>>> }
>>>>> 
>>>>> #endif
>>>>> 
>>>>> Modified: llvm/trunk/lib/Support/ManagedStatic.cpp
>>>>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/ManagedStatic.cpp?rev=219638&r1=219637&r2=219638&view=diff
>>>>> ==============================================================================
>>>>> --- llvm/trunk/lib/Support/ManagedStatic.cpp (original)
>>>>> +++ llvm/trunk/lib/Support/ManagedStatic.cpp Mon Oct 13 17:37:25 2014
>>>>> @@ -16,16 +16,22 @@
>>>>> #include "llvm/Support/Atomic.h"
>>>>> #include "llvm/Support/Mutex.h"
>>>>> #include "llvm/Support/MutexGuard.h"
>>>>> +#include "llvm/Support/Threading.h"
>>>>> #include <cassert>
>>>>> using namespace llvm;
>>>>> 
>>>>> static const ManagedStaticBase *StaticList = nullptr;
>>>>> +static sys::Mutex *ManagedStaticMutex = nullptr;
>>>>> 
>>>>> -static sys::Mutex& getManagedStaticMutex() {
>>>>> +static void initializeMutex() {
>>>>> +  ManagedStaticMutex = new sys::Mutex();
>>>>> +}
>>>>> +
>>>>> +static sys::Mutex* getManagedStaticMutex() {
>>>>> // We need to use a function local static here, since this can get called
>>>>> // during a static constructor and we need to guarantee that it's initialized
>>>>> // correctly.
>>>>> -  static sys::Mutex ManagedStaticMutex;
>>>>> +  llvm_call_once<initializeMutex>();
>>>>> return ManagedStaticMutex;
>>>>> }
>>>>> 
>>>>> @@ -33,7 +39,7 @@ void ManagedStaticBase::RegisterManagedS
>>>>>                                             void (*Deleter)(void*)) const {
>>>>> assert(Creator);
>>>>> if (llvm_is_multithreaded()) {
>>>>> -    MutexGuard Lock(getManagedStaticMutex());
>>>>> +    MutexGuard Lock(*getManagedStaticMutex());
>>>>> 
>>>>>   if (!Ptr) {
>>>>>     void* tmp = Creator();
>>>>> @@ -83,8 +89,13 @@ void ManagedStaticBase::destroy() const
>>>>> 
>>>>> /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables.
>>>>> void llvm::llvm_shutdown() {
>>>>> -  MutexGuard Lock(getManagedStaticMutex());
>>>>> +  {
>>>>> +    MutexGuard Lock(*getManagedStaticMutex());
>>>>> +
>>>>> +    while (StaticList)
>>>>> +      StaticList->destroy();
>>>>> +  }
>>>>> 
>>>>> -  while (StaticList)
>>>>> -    StaticList->destroy();
>>>>> +  delete ManagedStaticMutex;
>>>>> +  ManagedStaticMutex = nullptr;
>>>>> }
>>>>> 
>>>>> 
>>>>> _______________________________________________
>>>>> llvm-commits mailing list
>>>>> llvm-commits at cs.uiuc.edu
>>>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>> 
>>> _______________________________________________
>>> llvm-commits mailing list
>>> llvm-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141022/b7a6b118/attachment.html>


More information about the llvm-commits mailing list