마지막으로 문제가 무엇인지 알아 냈습니다. 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를 내에서이
- 실행 및 EXE 내에서 memset 함수를
- 실행을 수행합니다 (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
당신은 것을 볼 수 있습니다 모든 케이스가 이제 예상대로 작동합니다!
문제를 해결하기 위해 관리되었지만 수정 이유가 확실하지 않습니다. 세마포어 함수를 호출하는 코드는 .so 내부 클래스에 있었고 실행 파일 자체에서 호출되었습니다. 코드를 cpp 파일에서 헤더로 옮기면 (즉, 클래스를 실행 파일로 효과적으로 인라인합니다) 문제가 사라집니다. 그래서, RHEL5.4에서 sem_timedwait를 .so에서 호출하면 실패합니다.하지만 실행 파일에서 동일한 호출을하면 작동합니다. 그리고 나는 이유를 모르겠다 ... – pxb