2009-12-02 7 views
5

pthreads sem_timedwait를 사용하여 RedHat Enterprise Linux 시스템에서 비정상적인 동작을 보았습니다. 버전 5.3 이상에서만 발생합니다.RedHat Enterprise Linux 5.3 이상에서는 sem_timedwait가 제대로 지원되지 않습니까?

sem_init이있는 백그라운드 스레드에서 세마포를 만들면 오류가 반환되지 않습니다. sem_timedwait을 실행하면 errno = 38 (ENOSYS)로 즉각 반환되어 지원되지 않음을 나타냅니다.

주 스레드에서 똑같은 작업을 수행하면 예상대로 작동하며 sem_timedwait에서 오류가 발생하지 않습니다.

RHEL 5.2 또는 이전 버전에서는 표시되지 않습니다. 우리는 gcc 3.2.3과 4.1.2로 코드를 컴파일 해보고 동일한 결과를 얻었으므로 런타임 문제로 보입니다.

그래서, (마지막으로) 내 질문

1) 다른 사람이 본 적있다? 2) RHEL 5.3 이후의 알려진 문제점입니까? 3) sem_timedwait를 사용하여 단일 스레드를 잠자 게합니다. 같은 일을 리눅스가 할 수있는 대안은 무엇입니까?

다른 질문의 사본 인 경우 알려주십시오. 나는 보았지만 동일한 질문을 가진 하나를 찾을 수 없다. 우리가 사용하는 OSX가 아닌 OSX에 대해서도 비슷한 질문을 찾을 수있다.

감사 PXB는

는 업데이트 : 단지 다음과 같은 결과를 좀 더 테스트를 수행 :

  • 나는 (와 RHEL5.4 상자에 GCC 4.1.2를 사용하여 64 비트 빌드를 수행하는 경우 -L/usr/lib64 및 -lstdC++ -lrt) RHEL5의 64 비트 설치에서 실행하면 올바르게 작동합니다.
  • RHEL5.1 상자에서 gcc 4.1.2를 사용하여 32 비트 빌드를 수행하면 -L/usr/lib 및 -lstdC++ -lrt) 정확히 동일한 64 비트 RHEL5 상자에서 실행하면 sem_timedwait에서 ENOSYS 오류가 발생합니다.

그래서 RHEL5.4 (및 RHEL5.3)에서 64 비트와 32 비트 런타임 라이브러리의 차이가있는 것으로 보입니다. 유일한 다른 차이점은 RHEL5.1 및 RHEL5.4 상자 각각 32 비트 및 64 비트 빌드가 수행되었다는 것입니다.

+0

문제를 해결하기 위해 관리되었지만 수정 이유가 확실하지 않습니다. 세마포어 함수를 호출하는 코드는 .so 내부 클래스에 있었고 실행 파일 자체에서 호출되었습니다. 코드를 cpp 파일에서 헤더로 옮기면 (즉, 클래스를 실행 파일로 효과적으로 인라인합니다) 문제가 사라집니다. 그래서, RHEL5.4에서 sem_timedwait를 .so에서 호출하면 실패합니다.하지만 실행 파일에서 동일한 호출을하면 작동합니다. 그리고 나는 이유를 모르겠다 ... – pxb

답변

6

마지막으로 문제가 무엇인지 알아 냈습니다. RHEL 5.4에서 sem_init을 호출하면 sem_timedwait을 실행하면 코드가있는 위치, sem_t를 소유 한 객체가 힙 또는 스택에 있는지 여부 등에 따라 시간 초과 대기의 다소 임의의 동작이 발생합니다. 시간 초과 대기는 즉시 반환됩니다 errno = 38 (ENOSYS)와 함께, 때때로 리턴되기 전에 올바르게 기다린다. 나는 문제가 해결 및 Valgrind의 보고서 오류를 간다 RHEL 5.2에 정확히 같은 코드를 실행하면

==32459== Thread 2: 
==32459== Syscall param futex(op) contains uninitialised byte(s) 
==32459== at 0x406C78: sem_timedwait (in /lib/libpthread-2.5.so) 
==32459== by 0x8049F2E: TestThread::Run() (in /home/stsadm/semaphore_test/semaphore_test) 
==32459== by 0x44B2307: nxThread::_ThreadProc(void*) (in /home/stsadm/semaphore_test/libcore.so) 
==32459== by 0x4005AA: start_thread (in /lib/libpthread-2.5.so) 
==32459== by 0x355CFD: clone (in /lib/libc-2.5.so) 

: Valgrind의를 통해 그것을 실행

이 오류를 제공합니다.

나는 문제는 버그가 RHEL5.4에 세마포어 또는 무언가에 도입 된 것 같습니다, 5.4

memset(&_semaphore, 0, sizeof(sem_t)); 

그래서 RHEL에 사라질 sem_init 호출하기 전에 sem_t 변수에 memset 함수를 할 경우 그 그것을 내부적으로 사용하고 sem_init가 sem_t 메모리를 올바르게 초기화하지 않습니다. 또는 sem_timed wait는 전에 없었던 방식으로 민감하게 변경되었습니다.

흥미롭게도 sem_init은 작동하지 않는다는 오류를 반환하지 않습니다. 예상되는 동작은 sem_init는 sem_t의 기억을 intialise 없다는 것입니다 그 호출자에게 달려 경우

또는 다음 동작은 확실히 RHEL 5.4

PXB

업데이트로 변경되었습니다 - 여기 있어요 다른 누군가가 시험해보고 싶어하는 경우를 대비 한 테스트 케이스 코드. 이 문제는 .so에서만 sem_timedwait가 호출되고 32 비트 바이너리 (물론 32 비트 libs와 연결)로 빌드 된 경우에만 발생합니다.

MAIN.CPP에서 semtest.cpp

#include <semaphore.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <time.h> 

void semtest(int semnum, bool initmem) 
{ 
     sem_t sem; 

     if (initmem) 
     { 
       memset(&sem, 0, sizeof(sem_t)); 
       printf("sem %d: memset size = %d\n", semnum, sizeof(sem_t)); 
     } 

     errno = 0; 
     int res = sem_init(&sem, 0, 0); 

     printf("sem %d: sem_init res = %d, errno = %d\n", semnum, res, errno); 

     timespec ts; 
     clock_gettime(CLOCK_REALTIME, &ts); 
     ts.tv_sec += 1; 

     errno = 0; 
     res = sem_timedwait(&sem, &ts); 

     printf("sem %d: sem_timedwait res = %d, errno = %d\n\n", semnum, res, errno); 
} 

2)에서

1)())

#include <semaphore.h> 
#include <stdio.h> 
#include <string.h> 
#include <errno.h> 
#include <time.h> 

extern void semtest(int semnum, bool initmem); 

void semtest_in_exe(int semnum, bool initmem) 
{ 
     sem_t sem; 

     if (initmem) 
     { 
       memset(&sem, 0, sizeof(sem_t)); 
       printf("sem %d: memset size = %d\n", semnum, sizeof(sem_t)); 
     } 

     errno = 0; 
     int res = sem_init(&sem, 0, 0); 

     printf("sem %d: sem_init res = %d, errno = %d\n", semnum, res, errno); 

     timespec ts; 
     clock_gettime(CLOCK_REALTIME, &ts); 
     ts.tv_sec += 1; 

     errno = 0; 
     res = sem_timedwait(&sem, &ts); 

     printf("sem %d: sem_timedwait res = %d, errno = %d\n\n", semnum, res, errno); 
} 

int main(int argc, char* argv[], char** envp) 
{ 
     semtest(1, false); 
     semtest(2, true); 
     semtest_in_exe(3, false); 
     semtest_in_exe(4, true); 
} 

3 그래서 우리는 EXE에서와 .so를 내에서 실행 비교할 수 있습니다 중복 검사 기능이 있습니다 여기 메이크 파일이 있습니다

  • 실행에서 memset 함수
  • 을하지 않고 .so를 내에서 memset 함수를
  • 실행하지 않고 .so를 내에서

    1. 실행 및 EXE 내에서 memset 함수를
    2. 실행을 수행합니다 (210)
      all: main 
      
      semtest.o: semtest.cpp 
           gcc -c -fpic -m32 -I /usr/include/c++/4.1.2 -I /usr/include/c++/4.1.2/i386-redhat-linux semtest.cpp -o semtest.o 
      
      libsemtest.so: semtest.o 
           gcc -shared -m32 -fpic -lstdc++ -lrt semtest.o -o libsemtest.so 
      
      main: libsemtest.so 
           gcc -m32 -L . -lsemtest main.cpp -o semtest 
      

      테스트 케이스는 exe 안에 do memset

    그리고 RHEL5.4에서 실행되는 결과는 다음과 같습니다.

    sem 1: sem_init res = 0, errno = 0 
    sem 1: sem_timedwait res = -1, errno = 38 
    
    sem 2: memset size = 16 
    sem 2: sem_init res = 0, errno = 0 
    sem 2: sem_timedwait res = -1, errno = 110 
    
    sem 3: sem_init res = 0, errno = 0 
    sem 3: sem_timedwait res = -1, errno = 110 
    
    sem 4: memset size = 16 
    sem 4: sem_init res = 0, errno = 0 
    sem 4: sem_timedwait res = -1, errno = 110 
    

    당신은 한 즉시 반환 errno를 가진 경우를 볼 수있다 = 38

    우리가 RHEL5.2에 동일한 코드를 실행하면 우리는 다음과 같은 얻을 :

    sem 1: sem_init res = 0, errno = 0 
    sem 1: sem_timedwait res = -1, errno = 110 
    
    sem 2: memset size = 16 
    sem 2: sem_init res = 0, errno = 0 
    sem 2: sem_timedwait res = -1, errno = 110 
    
    sem 3: sem_init res = 0, errno = 0 
    sem 3: sem_timedwait res = -1, errno = 110 
    
    sem 4: memset size = 16 
    sem 4: sem_init res = 0, errno = 0 
    sem 4: sem_timedwait res = -1, errno = 110 
    

    당신은 것을 볼 수 있습니다 모든 케이스가 이제 예상대로 작동합니다!

  • +0

    +1 감사에 대한 후속 – pmg

    +0

    고마워, 도와 줘. 그러나 나는 우분투 9.10에있었습니다. 코드가 작동하기 시작했습니다. 조금만 변경하면 오류가 발생합니다 (errno 38로 시작되지 않음). 그리고 memset이 문제를 해결했습니다. – inazaruk

    2

    semtest[email protected]_2.1, 및 libsemtest.so[email protected]_2.0를 호출 호출하는 것 같다.

    sem_timedwait() 버전 2.1이 필요합니다.

    libsemtest.so을 만드는 규칙에 -lpthread을 추가하여 네 가지 테스트 모두에 대해 올바른 결과를 얻었습니다.

    나는 이것을 RH 5.3에서 테스트했다.

    +1

    이것은 실제로 올바른 접근 방법입니다 (수락 된 대답은 아닙니다). –

    +0

    왜 그런 종류의 불일치가 발생합니까? 각 라이브러리를 lpthread와 연결하여 라이브러리가 일관성을 유지할 수있는 유일한 방법입니까? – KyleL