Bug 66830

Summary: Problem with C++ unique symbols in plugins
Product: gcc Reporter: pleuba
Component: c++Assignee: Not yet assigned to anyone <unassigned>
Status: UNCONFIRMED ---    
Severity: normal CC: webrown.cpp
Priority: P3    
Version: 4.9.1   
Target Milestone: ---   
See Also: https://sourceware.org/bugzilla/show_bug.cgi?id=16805
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed:
Attachments: Test program that reproduce the problem

Description pleuba 2015-07-10 13:05:16 UTC
I have a problem in an application loading several plugins using the same library containing a static variable (object of class, not POD) in an inline function.

The compiler generates STB_GNU_UNIQUE symbols for the the variable and its guard.

Scenario:
- dlopen plugin1 (dynamic loader detect the unique variables and mark DSO as not unloadable)
- dlopen plugin2 (dynamic loader will uses the unique variables of plugin1 and do NOT mark DSO as unloadable, because its unique symbol is not used)
- Invoke some code in plugin2 that call the inline function, so the variable (of plugin 1) is constructed and its guard marked initialized, but the destructor of the variable is incorrectly registered with __cxa_atexit to be called on unload of plugin2.
- dlclose the plugin2, so it is unloaded, __CXA_finalize calls the destructor of the global variable owned by plugin1 !, keeping the guard marked as initialised.
- If we reload the plugin2, it will not reconstruct the global variable as it is still marked as initialised and access it. This results either immediately or later in crash.

Using compiler flag -fno-gnu-unique prevents the problem.

Is this problem already known ?

Philippe
Comment 1 pleuba 2015-07-21 15:02:23 UTC
Created attachment 36022 [details]
Test program that reproduce the problem

By executing the script test.sh, you can easily reproduce the problem.

core dump shows that the second call to plugin2.so crashes.

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f27fd946bc5 in Test::set (i=2) at lib.hpp:10
10	      *test.pi = i;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.149.el6.x86_64 libgcc-4.4.7-11.el6.x86_64 libstdc++-4.4.7-11.el6.x86_64
(gdb) bt
#0  0x00007f27fd946bc5 in Test::set (i=2) at lib.hpp:10
#1  0x00007f27fd946b3e in plugin2_test () at plugin2.cpp:6
#2  0x000000000040063c in load_plugin2 () at test.cpp:8
#3  0x0000000000400676 in main (argc=1, argv=0x7fffa4ea2908) at test.cpp:17
(gdb)
Comment 2 Jonathan Wakely 2015-07-21 17:11:58 UTC
(In reply to pleuba from comment #0)
> Is this problem already known ?

Yes, it has been known for a long time, but it's not an ideal situation and there is currently no better solution than -fno-gnu-unique
Comment 3 pleuba 2015-07-21 20:05:18 UTC
Is this problem/behavior referenced or documented somewhere? I did not find any explanation on the internet. 

It take me some time to understand it, and if we can avoid others to spend this time too.

Are they any plans to fix this or disable unique symbols by default ?

Philippe
Comment 4 Carlos O'Donell 2016-03-31 01:52:35 UTC
(In reply to pleuba from comment #3)
> Is this problem/behavior referenced or documented somewhere? I did not find
> any explanation on the internet. 
> 
> It take me some time to understand it, and if we can avoid others to spend
> this time too.
> 
> Are they any plans to fix this or disable unique symbols by default ?

The dynamic loader could mark all users of an STB_GNU_UNIQUE symbol as RTLD_NODELETE. It seems like the only answer.

That would mean you can't unload any of your plugins, and would make using C++ for dynamic plugin work very difficult. A long-running process could never change these plugins. The author of the plugins would have to understand intimate ABI details to write unloadable plugins or use another language that doesn't have these problems.
Comment 5 Richard Biener 2016-07-25 10:38:13 UTC
*** Bug 71971 has been marked as a duplicate of this bug. ***