2015-01-17 3 views
0

pthread 라이브러리의 pthread_atfork 함수를 사용하여 하위 후크를 등록하는 이전 응용 프로그램이 있습니다. 나는 glibc 2.14.90을 사용하는 새로운 빌드 환경으로 응용 프로그램을 이동하는 중입니다. pthread_atfork는 2002 년 pthread 라이브러리에서 근본적으로 제거 된 것으로 보입니다. 우리가 만드는 공유 라이브러리 중 하나는 더 이상 컴파일되지 않습니다. 아이 후크로 _INIT-nostartfiles를 선언 할 때 pthread_atfork이 컴파일되지 않습니다.

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는 파일, 뮤텍스, 초기화 매개 변수 등을 초기화하는 초기화 함수 인 startUp을 실행하는 새로운 스레드를 생성합니다.

pthread_atfork가 glibc 2.14에서 숨겨져 있기 때문에 다른 방법이 있습니까? init가 fork에서 실행되도록 같은 종류의 후크를 등록 하시겠습니까? 빌드 환경의 이식성을 유지하기 위해 표준 lib를 수정하지 않고 사용하는 것을 선호합니다.

의 glibc 2.14 소스 코드 (pthread_atfork 명령 파일이 NPTL 디렉토리 아래에) 관심이있는 사람들을 위해, 여기에 있습니다 :

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

컴파일 에러가 나는 나타날 수

의 gcc -g -nostartfiles -o MTO .so를 -shared -I mto.c -lnsl -lresolv -lrt -lm -lpthread -ldl

는/usr/빈/LD : /usr/lib/libpthread_nonshared.a(pthread_atfork.oS)에 대한 재배치 R_386_GOTOFF 정의가없는 내장 사양을 사용하여 공유 객체를

$ gcc가 -v

을 할 때 사용할 수 없습니다 숨겨진 기호`__dso_handle을 '이네. COLLECT_GCC = gcc가 COLLECT_LTO_WRAPPER =는/usr/libexec 디렉토리/GCC /는 i686-레드햇 리눅스/4.6.3/LTO-래퍼 대상 :는 i686-레드햇 리눅스 로 구성 : ../configure --prefix =/USR - -mandir =/usr/share/man --infodir =/usr/share/info --with-bugurl = http://bugzilla.redhat.com/bugzilla - 사용 가능 부트 스트랩 - 사용 가능 공유 - 사용 가능 스레드 = posix - 사용 가능 확인 = 릴리스 --with-system-zlib --enable -__ cxa_atexit --disable-libunwind - 예외 - 가능 -gnu-unique-object - 가능 링커 빌드 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 - 사용 가능 libgcj-multifile - 사용 가능 - java-maintainer-mode --with-ecj-jar =/usr/share/java/eclipse-ecj.jar --disable-libjava -multilib --with-ppl --with-cloog --with-tune = 일반 --with-arch = i686 --build = i686-redhat-linux 스레드 모델 : POSIX 버전의 gcc 4.6.3 20120306 (레드햇 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 

감사합니다.

+3

'pthread_atfork'가 제거되었다고 생각하는 이유가 확실하지 않습니다. 그렇지 않았습니다. 실제 문제가 발생하면 오류 메시지가 표시됩니다. '_init'는 함수에 특히 나쁜 이름이라는 것을 명심하십시오. 예약 된 네임 스페이스에 있으므로 연결 프로세스에 의해 특별하게 취급 될 수 있습니다. –

+1

['pthread_atfork()'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_atfork.html)에 대한 POSIX 2008 사양의 이론적 근거를 읽고 과거 시제를 많이 볼 수 있습니다 : _' pthread_atfork()'함수는 제공 할 예정이었습니다 ... 예상 된 사용법은 ... 이론 상으로는 좋지만 실용적이지는 않습니다 ... 뮤텍스와 잠금을 통해 비 원자 연산을 보호해야하는 기능에 적합한 솔루션이 없습니다 ... POSIX .1 표준은 ... 멀티 스레드 프로세스에서 fork() 이후의 자식 프로세스가 비동기 신호 안전 인터페이스만을 호출 할 것을 요구합니다. _ –

+0

@JonathanLeffler : POSIX에서는 비공식적으로 사용되지 않지만 glibc에서는 제거되지 않았습니다. , 여전히 POSIX의 고대 버전을 지원하려고 시도하고 있으며, 현재의 POSIX도 여전히'pthread_atfork'를 제공합니다. –

답변

1

외부 래퍼 함수 pthread_atfork이 라이브러리를 식별 할 수 있도록 libpthread_nonshared.a으로 이동 된 것 같습니다. 아마도 라이브러리가 언로드 된 경우/설치된 핸들러를 제거 할 수 있습니다. 이것은 의도적으로 생략 한 시작 파일에 정의 된 __dso_handle 기호를 참조하여 수행됩니다. 당신은 이것을 할 수 없습니다. 시작 파일 생략은 일부 저수준 목적에서만 유효합니다. 그것은 표준 라이브러리의 어떤 부분을 링크하는 것과 호환되지 않습니다.

은 분명히 당신이 -nostartfiles을 사용하고있는 이유는 같은 이름의 함수와 충돌에 -nostartfiles없이이 링커 오류가 발생하기 때문에, 라이브러리가로드 될 때 실행됩니다 자신의 _init 기능을 쓸 수있다 crti.o. 불행히도 이것은 잘못된 수정입니다.

라이브러리로드시 코드를 실행하도록 _init을 재정의하는 것은 오래 전에 권장되지 않는 지원되지 않는 핵입니다. 라이브러리로드시 코드를 실행하는 올바른 방법은 실행하려는 함수에 __attribute__((__constructor__))을 적용하는 것입니다. 함수와 충돌하지 않는 이름을 주거나 그냥 static으로 만들면 이름 충돌에 대해 걱정할 필요가 없습니다.

+0

이상하게도,'__attribute __ ((__ constructor__)) _init (void)'선언은 이미 파일에 있었지만 맨 위에있는'#ifdef (linux) '문으로 치워졌습니다. 함수 이름이 변경되지 않은 이유는 무엇입니까? 아마 gcc의 아주 오래된 버전에서이 코드를 유지할 수있는 게으름이거나 시도 일 것입니다. 이 코드는 솔라리스의 sun 컴파일러 하에서 컴파일해야만합니다. 솔라리스는'#defdef _init _localInit'을'# ifdef' 문에 넣어서 초기화합니다. _init 함수의 이름을 변경하고 -nostartfiles (및 _fini)를 제거했습니다. 도움을 주셔서 감사합니다. – ktbiz

관련 문제