pthread_atfork 声明 -nostartfiles 时编译失败
pthread_atfork fails to compile when declaring -nostartfiles
我有一个旧应用程序使用 pthread 库中的 pthread_atfork 函数来注册子挂钩。我正在将应用程序移动到使用 glibc 2.14.90 的较新构建环境。 pthread_atfork 似乎早在 2002 年就已从 pthread 库中删除,我们创建的共享库之一将不再编译。
这里是有问题的代码:
void
_init(void)
{
static int first = 1;
if ( first ) {
pthread_atfork(NULL,NULL,_init);
first = 0;
}
{
pthread_t tid;
pthread_create(&tid,0,startUp,0);
}
return;
}
pthread_atfork 调用将 _init 注册为子挂钩,每次有分叉时都会在子进程中 运行。 Init 只是创建一个新线程来执行 startUp,它是一个初始化函数,用于设置诸如文件、互斥锁、读取初始化参数等内容...
由于 pthread_atfork 隐藏在 glibc 2.14 中,是否有另一种方法来注册相同类型的钩子,以便 init 在 fork 时获得 运行?我宁愿使用标准库而不做任何修改,以保持构建环境的可移植性。
glibc 2.14 源代码在这里,感兴趣的可以参考(pthread_atfork 文件在 nptl 目录下):
我收到的编译错误:
gcc -g -nostartfiles -o mto.so -shared -I mto.c -lnsl -lresolv -lrt -lm -lpthread -ldl
/usr/bin/ld: /usr/lib/libpthread_nonshared.a(pthread_atfork.oS): 重定位R_386_GOTOFF对未定义的隐藏符号`__dso_handle'不能制作共享对象时使用
$ gcc -v
使用内置规格。
COLLECT_GCC=海湾合作委员会
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-redhat-linux/4.6.3/lto-wrapper
目标:i686-redhat-linux
配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique -object --enable-linker-build-id --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable -java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with -tune=generic --with-arch=i686 --build=i686-redhat-linux
线程模型:posix
gcc 版本 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC)
$ ldd --version
ldd(GNU libc)2.14.90
版权所有 (C) 2011 Free Software Foundation, Inc.
这是免费软件;有关复制条件,请参阅来源。没有
保修单;甚至不是为了特定目的的适销性或适用性。
由 Roland McGrath 和 Ulrich Drepper 撰写。
$ nm /usr/lib/libpthread.a|grep -C 1 atfork
00008150 W __pread64
000060b0 T __pthread_atfork
00002ab0 T __pthread_attr_destroy
--
00007ba0 W __recvmsg
U __register_atfork
00008c10 T __res_state
--
00008150 W pread64
000060b0 T pthread_atfork
00002ab0 T pthread_attr_destroy
.
$ nm /usr/lib/libpthread_nonshared.a
pthread_atfork.oS:
U _GLOBAL_OFFSET_TABLE_
w __dso_handle
00000000 T __i686.get_pc_thunk.bx
00000000 T __pthread_atfork
U __register_atfork
00000000 T pthread_atfork
感谢您的宝贵时间。
你的问题是外包装函数 pthread_atfork
似乎已移至 libpthread_nonshared.a
以便它可以识别调用它的库,大概这样可以删除已安装的处理程序 if/when 库被卸载,它通过引用启动文件中定义的 __dso_handle
符号来实现这一点,您有意省略了该符号。 你不能这样做。 省略启动文件仅对某些低级用途有效;它与链接标准库的任何部分都不兼容。
显然您使用 -nostartfiles
的原因是能够编写您自己的 _init
函数,该函数将在加载库时 运行,因为没有 -nostartfiles
由于与 crti.o
中的同名函数冲突,它会导致链接器错误。不幸的是,这是错误的修复。
在库加载时将 _init
重新定义为 运行 代码是一种不受支持的 hack,很久以前就被弃用了。在库加载时 运行 代码的正确方法是将 __attribute__((__constructor__))
应用于您想要 运行 的函数。给函数起一个不会与任何东西冲突的名称,或者直接将其命名为 static
这样您就不必担心它的名称冲突。
我有一个旧应用程序使用 pthread 库中的 pthread_atfork 函数来注册子挂钩。我正在将应用程序移动到使用 glibc 2.14.90 的较新构建环境。 pthread_atfork 似乎早在 2002 年就已从 pthread 库中删除,我们创建的共享库之一将不再编译。
这里是有问题的代码:
void
_init(void)
{
static int first = 1;
if ( first ) {
pthread_atfork(NULL,NULL,_init);
first = 0;
}
{
pthread_t tid;
pthread_create(&tid,0,startUp,0);
}
return;
}
pthread_atfork 调用将 _init 注册为子挂钩,每次有分叉时都会在子进程中 运行。 Init 只是创建一个新线程来执行 startUp,它是一个初始化函数,用于设置诸如文件、互斥锁、读取初始化参数等内容...
由于 pthread_atfork 隐藏在 glibc 2.14 中,是否有另一种方法来注册相同类型的钩子,以便 init 在 fork 时获得 运行?我宁愿使用标准库而不做任何修改,以保持构建环境的可移植性。
glibc 2.14 源代码在这里,感兴趣的可以参考(pthread_atfork 文件在 nptl 目录下):
我收到的编译错误:
gcc -g -nostartfiles -o mto.so -shared -I mto.c -lnsl -lresolv -lrt -lm -lpthread -ldl
/usr/bin/ld: /usr/lib/libpthread_nonshared.a(pthread_atfork.oS): 重定位R_386_GOTOFF对未定义的隐藏符号`__dso_handle'不能制作共享对象时使用
$ gcc -v
使用内置规格。 COLLECT_GCC=海湾合作委员会 COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-redhat-linux/4.6.3/lto-wrapper 目标:i686-redhat-linux 配置为:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique -object --enable-linker-build-id --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable -java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with -tune=generic --with-arch=i686 --build=i686-redhat-linux 线程模型:posix gcc 版本 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC)
$ ldd --version
ldd(GNU libc)2.14.90 版权所有 (C) 2011 Free Software Foundation, Inc. 这是免费软件;有关复制条件,请参阅来源。没有 保修单;甚至不是为了特定目的的适销性或适用性。 由 Roland McGrath 和 Ulrich Drepper 撰写。
$ nm /usr/lib/libpthread.a|grep -C 1 atfork
00008150 W __pread64
000060b0 T __pthread_atfork
00002ab0 T __pthread_attr_destroy
--
00007ba0 W __recvmsg
U __register_atfork
00008c10 T __res_state
--
00008150 W pread64
000060b0 T pthread_atfork
00002ab0 T pthread_attr_destroy
.
$ nm /usr/lib/libpthread_nonshared.a
pthread_atfork.oS:
U _GLOBAL_OFFSET_TABLE_
w __dso_handle
00000000 T __i686.get_pc_thunk.bx
00000000 T __pthread_atfork
U __register_atfork
00000000 T pthread_atfork
感谢您的宝贵时间。
你的问题是外包装函数 pthread_atfork
似乎已移至 libpthread_nonshared.a
以便它可以识别调用它的库,大概这样可以删除已安装的处理程序 if/when 库被卸载,它通过引用启动文件中定义的 __dso_handle
符号来实现这一点,您有意省略了该符号。 你不能这样做。 省略启动文件仅对某些低级用途有效;它与链接标准库的任何部分都不兼容。
显然您使用 -nostartfiles
的原因是能够编写您自己的 _init
函数,该函数将在加载库时 运行,因为没有 -nostartfiles
由于与 crti.o
中的同名函数冲突,它会导致链接器错误。不幸的是,这是错误的修复。
在库加载时将 _init
重新定义为 运行 代码是一种不受支持的 hack,很久以前就被弃用了。在库加载时 运行 代码的正确方法是将 __attribute__((__constructor__))
应用于您想要 运行 的函数。给函数起一个不会与任何东西冲突的名称,或者直接将其命名为 static
这样您就不必担心它的名称冲突。