<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - ManagedStatic"
   href="https://bugs.llvm.org/show_bug.cgi?id=48221">48221</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>ManagedStatic
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>11.0
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Support Libraries
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>v.churavy@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Created <span class=""><a href="attachment.cgi?id=24181" name="attach_24181" title="Rough initial patch for ManagedStatic">attachment 24181</a> <a href="attachment.cgi?id=24181&action=edit" title="Rough initial patch for ManagedStatic">[details]</a></span>
Rough initial patch for ManagedStatic

Since many projects depend on LLVM, we recommend that distributions and
downstream user use symbol versioning to avoid conflicts between multiple LLVM
versions being loaded into the same process.

On Linux mesa implementations (OpenGL/OpenCL) use LLVM extensively and they are
generally built against the system LLVM. On the other hand front-ends like
Julia might want to use a version of LLVM that diverges from the system LLVM. 

What we have observed happening for several years is that users will get errors
like:

<span class="quote">> CommandLine Error: Option 'help-list' registered more than once!
> LLVM ERROR: inconsistency in registered CommandLine options</span >

- <a href="https://github.com/JuliaGPU/OpenCL.jl/issues/125">https://github.com/JuliaGPU/OpenCL.jl/issues/125</a>
- <a href="https://github.com/hughperkins/tf-coriander/issues/69">https://github.com/hughperkins/tf-coriander/issues/69</a>

Or segmentation faults:
- <a href="https://github.com/NixOS/nixpkgs/issues/97401">https://github.com/NixOS/nixpkgs/issues/97401</a>
- <a href="https://github.com/JuliaLang/julia/issues/37200#issuecomment-729046989">https://github.com/JuliaLang/julia/issues/37200#issuecomment-729046989</a>

What this boils down to is that despite symbol versioning wires get crossed and
the state of the two loaded LLVM version aliases each other.

After I building mesa, my system LLVM and Julia's LLVM with debuginformation I
get the following interesting backtrace:

```
julia:
/home/vchuravy/src/julia/deps/srccache/llvm-11.0.0/include/llvm/Support/CommandLine.h:851:
void llvm::cl::parser<DataType>::addLiteralOption(llvm::StringRef, const DT&,
llvm::StringRef) [with DT = llvm::FunctionPass* (*)(); DataType =
llvm::FunctionPass* (*)()]: Assertion `findOption(Name) == Values.size() &&
"Option already exists!"' failed.

Thread 1 "julia" received signal SIGABRT, Aborted.
0x00007ffff7dda615 in raise () from /usr/lib/libc.so.6
(gdb) bt
#0  0x00007ffff7dda615 in raise () from /usr/lib/libc.so.6
#1  0x00007ffff7dc3862 in abort () from /usr/lib/libc.so.6
#2  0x00007ffff7dc3747 in __assert_fail_base.cold () from /usr/lib/libc.so.6
#3  0x00007ffff7dd2bf6 in __assert_fail () from /usr/lib/libc.so.6
#4  0x00007ffff0a8014e in llvm::cl::parser<llvm::FunctionPass*
(*)()>::addLiteralOption<llvm::FunctionPass* (*)()> (this=0x7ffff72fce68
<RegAlloc+168>, 
    Name=..., 
    V=@0x7fffffff9bc0: 0x7fffa6d8ff40 <llvm::createBasicRegisterAllocator()>, 
    HelpStr=...)
    at
/home/vchuravy/src/julia/deps/srccache/llvm-11.0.0/include/llvm/Support/CommandLine.h:851
#5  0x00007ffff0a83884 in
llvm::RegisterPassParser<llvm::RegisterRegAlloc>::NotifyAdd
(this=0x7ffff72fce60 <RegAlloc+160>, N=..., 
    C=0x7fffa6d8ff40 <llvm::createBasicRegisterAllocator()>, D=...)
    at
/home/vchuravy/src/julia/deps/srccache/llvm-11.0.0/include/llvm/CodeGen/MachinePassRegistry.h:162
#6  0x00007fffa67b9bb9 in llvm::MachinePassRegistry<llvm::FunctionPass*
(*)()>::Add (Node=0x7fffab14a900 <basicRegAlloc>, 
    this=0x7fffab14a8e0
<llvm::RegisterRegAllocBase<llvm::RegisterRegAlloc>::Registry>) at
../include/llvm/CodeGen/MachinePassRegistry.h:110
#7  llvm::RegisterRegAllocBase<llvm::RegisterRegAlloc>::RegisterRegAllocBase (
    C=0x7fffa6d8ff40 <llvm::createBasicRegisterAllocator()>, 
    D=0x7fffa91c73b8 "basic register allocator", N=0x7fffa91c73b2 "basic", 
--Type <RET> for more, q to quit, c to continue without paging--
    this=0x7fffab14a900 <basicRegAlloc>)
    at ../include/llvm/CodeGen/RegAllocRegistry.h:37
#8  llvm::RegisterRegAlloc::RegisterRegAlloc (
    C=0x7fffa6d8ff40 <llvm::createBasicRegisterAllocator()>, 
    D=0x7fffa91c73b8 "basic register allocator", N=0x7fffa91c73b2 "basic", 
    this=0x7fffab14a900 <basicRegAlloc>)
    at ../include/llvm/CodeGen/RegAllocRegistry.h:63
#9  __static_initialization_and_destruction_0 (__initialize_p=1, 
    __priority=65535) at ../lib/CodeGen/RegAllocBasic.cpp:44
#10 _GLOBAL__sub_I_RegAllocBasic.cpp(void) ()
    at ../lib/CodeGen/RegAllocBasic.cpp:333
#11 0x00007ffff7fe12de in call_init.part () from /lib64/ld-linux-x86-64.so.2
#12 0x00007ffff7fe13c8 in _dl_init () from /lib64/ld-linux-x86-64.so.2
#13 0x00007ffff7ed80e5 in _dl_catch_exception () from /usr/lib/libc.so.6
#14 0x00007ffff7fe5705 in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#15 0x00007ffff7ed8088 in _dl_catch_exception () from /usr/lib/libc.so.6
#16 0x00007ffff7fe4f3e in _dl_open () from /lib64/ld-linux-x86-64.so.2
#17 0x00007ffff7f8934c in ?? () from /usr/lib/libdl.so.2
#18 0x00007ffff7ed8088 in _dl_catch_exception () from /usr/lib/libc.so.6
#19 0x00007ffff7ed8153 in _dl_catch_error () from /usr/lib/libc.so.6
#20 0x00007ffff7f89b89 in ?? () from /usr/lib/libdl.so.2
#21 0x00007ffff7f893d8 in dlopen () from /usr/lib/libdl.so.2
#22 0x00007fffac9a6b90 in loader_open_driver.constprop ()
--Type <RET> for more, q to quit, c to continue without paging--
   from /usr/lib/libGLX_mesa.so.0
#23 0x00007fffac99cbe0 in dri3_create_screen.lto_priv ()
   from /usr/lib/libGLX_mesa.so.0
#24 0x00007fffac9856e9 in __glXInitialize () from /usr/lib/libGLX_mesa.so.0
```

In particular I find note-worthy how from the initializer:

```
#10 _GLOBAL__sub_I_RegAllocBasic.cpp(void) ()
    at ../lib/CodeGen/RegAllocBasic.cpp:333
```

we meander to:
```
#5  0x00007ffff0a83884 in
llvm::RegisterPassParser<llvm::RegisterRegAlloc>::NotifyAdd
(this=0x7ffff72fce60 <RegAlloc+160>, N=..., 
    C=0x7fffa6d8ff40 <llvm::createBasicRegisterAllocator()>, D=...)
    at
/home/vchuravy/src/julia/deps/srccache/llvm-11.0.0/include/llvm/CodeGen/MachinePassRegistry.h:162

```

Now I am unclear on how the wires get crossed here by the dynamic linker. My
assumption is this has to do with static variables, and perhaps those get
merged across the libraries?

Working with that hypothesis I added a prefix to the static variables used by
ManagedStatic  and that got me further, but while writing this up I am unsure
if that is a sufficient fix. I am baffled byt the behaviour since these static
variables are not exported ...

Thinking about this more an looking at the particular global variable:
`llvm::RegisterRegAllocBase<llvm::RegisterRegAlloc>::Registry`

```
nm -D ~/builds/julia/usr/lib/libLLVM-11.0.0jl.so |
~/builds/julia/usr/tools/llvm-cxxfilt | grep "llvm::RegisterRegAlloc"
0000000007f71780 u
llvm::RegisterRegAllocBase<llvm::RegisterRegAlloc>::Registry@@JL_LLVM_11.0
00000000016fe70e W void
llvm::cl::printOptionDiff<llvm::RegisterPassParser<llvm::RegisterRegAlloc>,
llvm::FunctionPass* (*)()>(llvm::cl::Option const&,
llvm::cl::generic_parser_base const&, llvm::FunctionPass* (* const&)(),
llvm::cl::OptionValue<llvm::FunctionPass* (*)()> const&, unsigned
long)@@JL_LLVM_11.0
00000000016f7cc9 W void llvm::cl::apply<llvm::cl::opt<llvm::FunctionPass*
(*)(), false, llvm::RegisterPassParser<llvm::RegisterRegAlloc> >, char [9],
llvm::cl::OptionHidden, llvm::cl::initializer<llvm::FunctionPass* (*)()>,
llvm::cl::desc>(llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >*, char const (&) [9],
llvm::cl::OptionHidden const&, llvm::cl::initializer<llvm::FunctionPass* (*)()>
const&, llvm::cl::desc const&)@@JL_LLVM_11.0
00000000016fa05c W void llvm::cl::apply<llvm::cl::opt<llvm::FunctionPass*
(*)(), false, llvm::RegisterPassParser<llvm::RegisterRegAlloc> >,
llvm::cl::initializer<llvm::FunctionPass* (*)()>,
llvm::cl::desc>(llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >*,
llvm::cl::initializer<llvm::FunctionPass* (*)()> const&, llvm::cl::desc
const&)@@JL_LLVM_11.0
00000000016f9176 W void llvm::cl::apply<llvm::cl::opt<llvm::FunctionPass*
(*)(), false, llvm::RegisterPassParser<llvm::RegisterRegAlloc> >,
llvm::cl::OptionHidden, llvm::cl::initializer<llvm::FunctionPass* (*)()>,
llvm::cl::desc>(llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >*, llvm::cl::OptionHidden
const&, llvm::cl::initializer<llvm::FunctionPass* (*)()> const&, llvm::cl::desc
const&)@@JL_LLVM_11.0
00000000016fa8c7 W void llvm::cl::apply<llvm::cl::opt<llvm::FunctionPass*
(*)(), false, llvm::RegisterPassParser<llvm::RegisterRegAlloc> >,
llvm::cl::desc>(llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >*, llvm::cl::desc
const&)@@JL_LLVM_11.0
00000000016f7c62 W std::function<void (llvm::FunctionPass* (*
const&)())>::function<llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc>
<span class="quote">>::Callback::'lambda'(llvm::FunctionPass* (* const&)()), void,</span >
void>(llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc>
<span class="quote">>::Callback::'lambda'(llvm::FunctionPass* (* const&)()))@@JL_LLVM_11.0</span >
00000000016f7c62 W std::function<void (llvm::FunctionPass* (*
const&)())>::function<llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc>
<span class="quote">>::Callback::'lambda'(llvm::FunctionPass* (* const&)()), void,</span >
void>(llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc>
<span class="quote">>::Callback::'lambda'(llvm::FunctionPass* (* const&)()))@@JL_LLVM_11.0</span >
0000000007ec4160 V vtable for
llvm::RegisterPassParser<llvm::RegisterRegAlloc>@@JL_LLVM_11.0
0000000007ec40f8 V vtable for llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >@@JL_LLVM_11.0
```

```
nm -D /usr/lib/libLLVM-11.0.0.so | ~/builds/julia/usr/tools/llvm-cxxfilt | grep
"llvm::RegisterRegAlloc"
00000000052188e0 u
llvm::RegisterRegAllocBase<llvm::RegisterRegAlloc>::Registry@@LLVM_11
0000000005142ec0 V typeinfo for
llvm::RegisterPassParser<llvm::RegisterRegAlloc>@@LLVM_11
0000000005142f60 V typeinfo for llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc>
<span class="quote">>::Callback::'lambda'(llvm::FunctionPass* (* const&)())@@LLVM_11</span >
0000000005142ef8 V typeinfo for llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >@@LLVM_11
000000000329e4c0 V typeinfo name for
llvm::RegisterPassParser<llvm::RegisterRegAlloc>@@LLVM_11
000000000329e680 V typeinfo name for llvm::cl::opt<llvm::FunctionPass* (*)(),
false, llvm::RegisterPassParser<llvm::RegisterRegAlloc>
<span class="quote">>::Callback::'lambda'(llvm::FunctionPass* (* const&)())@@LLVM_11</span >
000000000329e500 V typeinfo name for llvm::cl::opt<llvm::FunctionPass* (*)(),
false, llvm::RegisterPassParser<llvm::RegisterRegAlloc> >@@LLVM_11
00000000051434b8 V vtable for
llvm::RegisterPassParser<llvm::RegisterRegAlloc>@@LLVM_11
0000000005143540 V vtable for llvm::cl::opt<llvm::FunctionPass* (*)(), false,
llvm::RegisterPassParser<llvm::RegisterRegAlloc> >@@LLVM_11
```

To quote the `nm` man page:

```
           "u" The symbol is a unique global symbol.  This is a GNU extension
               to the standard set of ELF symbol bindings.  For such a symbol
               the dynamic linker will make sure that in the entire process
               there is just one symbol with this name and type in use.
```

So I would assume that issue might be that the dynamic linker ignores the
symbol version.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>