记录应用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...