简体   繁体   English

声明-nostartfiles时pthread_atfork无法编译

[英]pthread_atfork fails to compile when declaring -nostartfiles

I have an old application that uses the pthread_atfork function from the pthread library to register a child hook. 我有一个旧的应用程序,该应用程序使用pthread库中的pthread_atfork函数来注册子挂钩。 I'm in the process of moving the application to a newer build environment which uses glibc 2.14.90. 我正在将应用程序移至使用glibc 2.14.90的较新的构建环境。 pthread_atfork appears to have been essentially removed from the pthread library back in 2002, and one of the shared libraries we create will no longer compile. pthread_atfork在2002年似乎已从pthread库中删除,我们创建的共享库之一将不再编译。

Here is the code in question: 这是有问题的代码:

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;
}

The pthread_atfork call registers _init as a child hook, to be run in the child process every time there's a fork. pthread_atfork调用将_init注册为一个子钩子,每次有一个fork时就在子进程中运行。 Init just creates a new thread to execute startUp which is an initialization function that sets up stuff like files, mutexes, reads in initialization parameters, etc... Init只是创建一个新线程来执行startUp,这是一个初始化函数,用于设置文件,互斥对象,读取初始化参数等内容。

Since pthread_atfork is hidden in glibc 2.14, is there a another way to register the same kind of hook so that init gets run at fork? 由于pthread_atfork隐藏在glibc 2.14中,是否存在另一种方法来注册相同类型的钩子,以便init在fork上运行? I would prefer to use the standard lib without any modification, to preserve portability of the build environment. 我宁愿使用没有任何修改的标准库,以保留构建环境的可移植性。

glibc 2.14 source code is here, for those interested (pthread_atfork files are under the nptl directory): 对于那些感兴趣的人,这里是glibc 2.14源代码(pthread_atfork文件位于nptl目录下):

https://sourceware.org/git/?p=glibc.git;a=tree;h=d1e550124ee36b8b62af8984e4b829622a60f725;hb=356f8bc660a154a07b03da7c536831da5c8f74fe https://sourceware.org/git/?p=glibc.git;a=tree;h=d1e550124ee36b8b62af8984e4b829622a60f725;hb=356f8bc660a154a07b03da7c536831da5c8f74fe

Compilation error I receive: 我收到的编译错误:

gcc -g -nostartfiles -o mto.so -shared -I mto.c -lnsl -lresolv -lrt -lm -lpthread -ldl 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): relocation R_386_GOTOFF against undefined hidden symbol `__dso_handle' can not be used when making a shared object / usr / bin / ld:/usr/lib/libpthread_nonshared.a(pthread_atfork.oS):在创建共享库时,无法使用针对未定义隐藏符号'__dso_handle的重定位R_386_GOTOFF

$ gcc -v $ gcc -v

Using built-in specs. 使用内置规格。 COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/libexec/gcc/i686-redhat-linux/4.6.3/lto-wrapper Target: i686-redhat-linux Configured with: ../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 Thread model: posix gcc version 4.6.3 20120306 (Red Hat 4.6.3-2) (GCC) COLLECT_GCC = 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-版本

ldd (GNU libc) 2.14.90 Copyright (C) 2011 Free Software Foundation, Inc. This is free software; ldd(GNU libc)2.14.90版权所有(C)2011自由软件基金会,公司。 see the source for copying conditions. 请参阅复制条件的来源。 There is NO warranty; 没有保修; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 甚至不是出于适销性或针对特定目的的适用性。 Written by Roland McGrath and Ulrich Drepper. 由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

Thanks for your time. 谢谢你的时间。

Your problem is that the outer wrapper function pthread_atfork seems to have been moved to libpthread_nonshared.a so that it can identify the library calling it, presumably so that the installed handlers can be removed if/when the library is unloaded, and it achieves this by referencing the __dso_handle symbol which is defined in the start files, which you are intentionally omitting. 您的问题是外包装函数pthread_atfork似乎已移至libpthread_nonshared.a以便可以识别调用它的库,大概是这样,以便在/卸载库时可以删除已安装的处理程序,并通过以下方式实现此目的引用在起始文件中定义的__dso_handle符号,您有意忽略了__dso_handle符号。 You can't do this. 你做不到 Omitting start files is only valid for some low-level purposes; 省略开始文件仅对某些低级用途有效; it's not compatible with linking any part of the standard library. 它与链接标准库的任何部分都不兼容。

Apparently the reason you're using -nostartfiles is to be able to write your own _init function that will run when the library is loaded, since without -nostartfiles it causes a linker error due to a clash with the same-name function in crti.o . 显然,您使用-nostartfiles的原因是能够编写自己的_init函数,该函数将在加载库时运行,因为如果没有-nostartfiles ,则由于-nostartfiles与同名函数的冲突而导致链接器错误crti.o Unfortunately this is the wrong fix. 不幸的是,这是错误的修复。

Redefining _init to run code at library load time is an unsupported hack that was deprecated a long time ago. 重新定义_init以在库加载时运行代码是很久以前不推荐使用的一种不受支持的hack。 The correct way to run code at library load time is to apply __attribute__((__constructor__)) to the function you want to run. 在库加载时运行代码的正确方法是将__attribute__((__constructor__))应用于要运行的函数。 Give the function a name that won't clash with anything, or just make it static so you don't have to worry about its name clashing. 为函数指定一个不会与任何东西冲突的名称,或者只是使其保持static这样您就不必担心其名称冲突。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM