记录应用dlclose后so无奈卸载问题
问题形容
有一个相似插件的性能,应用dlopen形式加载一个so,降级so的时候,先dlclose,而后再dlopen加载。这样能够做到更换so的时候不必重新启动程序。原本所有运行的比拟好,但有一个so比拟奇怪,降级so后,某些函数无奈应用新的so外面的实现,还是旧的so中的实现。
问题定位
在gdb中应用info sharedlibrary命令查看加载的so,再应用lsof查看如下:
(gdb) info sharedlibrary 0x00007fff2132a2c0 0x00007fff213bc5f8 Yes /xxxx/xxx/libxxx.so[email protected]:~# lsof |grep libxxx.songinx 3391245 root mem REG 253,0 8604544 5250054 /xxx/xxx/libxxx.so
从这些信息中能够看到,目前正在应用的so的inode是5250054,而是用stat查看当初so的inode信息,发现inode是5377891,如下所示:
[email protected]:~# stat /xxx/xxx/libxxx.so File: /apisec/modules/component/sensitive_data/libs/libdi_rechk.so Size: 8604544 Blocks: 16808 IO Block: 4096 regular fileDevice: fd00h/64768d Inode: 5377891 Links: 1Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)Access: 2022-10-21 17:01:57.404283135 +0800Modify: 2022-10-21 15:48:29.000000000 +0800Change: 2022-10-21 17:00:23.423822609 +0800
两者inode不一样,阐明应用的不是同一个so文件,因为旧的so曾经被删除。但程序中曾经dlclose并从新dlopen了,于是从网上查找材料,有些材料中都说查看下是否有NODELET标记。于是应用readelf命令查看下:
[email protected]:~# readelf -d libxxx.so |grep NODELETE 0x000000006ffffffb (FLAGS_1) Flags: NODELETE
so中有此标识,则动静加载程序已被告知不要卸载库,所以调用dlclose后,不会从过程中卸载此so。
手动测试
本人写一个test.c的测试例子,代码如下:
#include <stdio.h>int test(){ printf("this is test function.\n"); return 0;}
应用如下编译命令编译:
gcc -fpic -shared -o libtest.so test.c
而后应用readelf命令查看是否有标识:
gcc -fpic -shared -o libtest.so test.c
发现没有任何输入。
从新应用以下命令编译并应用readelf命令查看:
gcc -fpic -shared -znodelete -o libtest.so test.creadelf -d libtest.so |grep NODELETE 0x000000006ffffffb (FLAGS_1) Flags: NODELETE
能够看到,增加了-znodelete选项后,编译出的so中曾经有了NODELETE选项。
-znodelete选项是链接器程序ld的一个参数,应用ld --help能够看到-znodelete选项的作用。有了此选项后,程序会常驻在过程中,在调用dlclose后,不会从过程中删除。除了nodelete选项,还有nodlopen等其它选项。
为什么这个so会增加-znodelete选项?
从开发so的人员那里理解到,其并没有手动增加这个选项,他的so是用go语言开发的,应用go build -buildmode=c-shared编译的c语言的so。
于是从网上搜寻相干问题,发现go语言生成的so中,目前不反对dlclose,应用的形式就是增加-znodelete选项。(https://github.com/golang/go/...)
目前(2022年10月24日),go语言反对dlclose在golang的github中仍然是一个open状体的bug:https://github.com/golang/go/...
参考资料
https://stackoverflow.com/que...
https://www.coder.work/articl...
https://docs.oracle.com/cd/E1...