[ZBXNEXT-3388] Load libraries in runtime with RTLD_LOCAL flag Created: 2016 Aug 19 Updated: 2019 Apr 10 |
|
Status: | Open |
Project: | ZABBIX FEATURE REQUESTS |
Component/s: | Agent (G), Proxy (P), Server (S) |
Affects Version/s: | 3.2.0alpha2 |
Fix Version/s: | None |
Type: | Change Request | Priority: | Major |
Reporter: | Glebs Ivanovskis (Inactive) | Assignee: | Unassigned |
Resolution: | Unresolved | Votes: | 0 |
Labels: | crash, dependencies | ||
Remaining Estimate: | Not Specified | ||
Time Spent: | Not Specified | ||
Original Estimate: | Not Specified |
Issue Links: |
|
Description |
Let's start with a small demonstration. Let's build a small application (test) linked against two libraries (liba.so and libe.so) depending on one and the same symbol (foo) from two different libraries (libb.so and libd.so). a.c: #include "a.h" #include "b.h" void a_foo(void) { foo(); } a.h: void a_foo(void); b.c:
#include <stdio.h>
void foo(void)
{
printf("bar\n");
}
b.h: void foo(void); d.c:
#include <stdio.h>
void foo(void)
{
printf("baz\n");
}
d.h: void foo(void); e.c: #include "d.h" #include "e.h" void e_foo(void) { foo(); } e.h: void e_foo(void); Let's build libraries: $ gcc -o libb.so b.c -fPIC -shared $ gcc -o libd.so d.c -fPIC -shared $ gcc -o liba.so a.c -lb -L. -fPIC -shared $ gcc -o libe.so e.c -ld -L. -fPIC -shared Let's first test them separately. #include "a.h" int main(void) { a_foo(); return 0; } test_e.c: #include "e.h" int main(void) { e_foo(); return 0; } $ export LD_LIBRARY_PATH=. $ gcc -o test_a test_a.c -la -L. $ gcc -o test_e test_e.c -le -L. $ ./test_a bar $ ./test_e baz So far everything is as expected. Now let's link both libraries to the same program. #include "a.h" #include "e.h" int main(void) { a_foo(); e_foo(); return 0; } Both a_foo() and e_foo() print "bar" or "baz" depending on -l flag order: $ gcc -o test_both test_both.c -la -le -L. $ ./test_both bar bar $ gcc -o test_both test_both.c -le -la -L. $ ./test_both baz baz If program has it's own symbol foo it gets even better. #include "a.h" #include "e.h" #include <stdio.h> void foo(void) { printf("foo\n"); } int main(void) { a_foo(); e_foo(); return 0; } Symbol foo from liba.so and libe.so gets resolved to the foo exported by the program itself: $ gcc -o test_own test_own.c -la -le -L. $ ./test_own foo foo But with a different approach it is possible to sort it out. #include <stdio.h> #include <dlfcn.h> void foo(void) { printf("foo\n"); } int main(void) { void *liba, *libe; void (*a_foo)(void); void (*e_foo)(void); liba = dlopen("liba.so", RTLD_NOW | RTLD_LOCAL); libe = dlopen("libe.so", RTLD_NOW | RTLD_LOCAL); a_foo = dlsym(liba, "foo"); e_foo = dlsym(libe, "foo"); foo(); a_foo(); e_foo(); dlclose(liba); dlclose(libe); return 0; } $ gcc -o test_rtld test_rtld.c -ldl $ ./test_rtld foo bar baz Most important question: How is it related to Zabbix? Zabbix depends on a number of libraries (cURL, Net-SNMP, OpenIPMI, DB client libraries, ...) which all require encryption libraries as a secondary dependency. Zabbix uses DB client libraries to access its database and links against UnixODBC which loads ODBC drivers which require DB client libraries too. Sometimes they all need different versions of the same library and inability to resolve symbols correctly (slight difference between "bar" and "baz" in the example above) often leads to crashes. |
Comments |
Comment by Glebs Ivanovskis (Inactive) [ 2016 Aug 19 ] |
List of potentially related tickets: ZBX-8005, |