Выполните объяснять-план по каждой версии, он скажет Вам почему.
Наконец выяснил, в чем проблема. В RHEL 5.4, если мы вызываем sem_init, а затем выполняем sem_timedwait, мы получаем несколько случайное поведение синхронизированного ожидания, в зависимости от того, где расположен код, находится ли объект, которому принадлежит sem_t, в куче или стеке и т. Д. Иногда синхронизированное ожидание возвращается немедленно с errno = 38 (ENOSYS) иногда он правильно ждет перед возвратом.
Запуск его через valgrind дает следующую ошибку:
==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)
Если я запускаю точно такой же код в RHEL 5.2, проблема исчезает, и valgrind не сообщает об ошибках.
Если я создаю memset для переменной sem_t перед вызовом sem_init, проблема исчезнет в RHEL 5.4
memset( &_semaphore, 0, sizeof( sem_t ) );
Итак, похоже, что ошибка была внесена в семафоры в RHEL5.4 или что-то, что он использует внутри, и sem_init неправильно инициализирует память sem_t. Или, Функция sem_timed wait была изменена, чтобы быть чувствительной к этому так, как не было раньше.
Интересно, что sem_init ни в одном случае не возвращает ошибку, чтобы указать, что это не сработало.
В качестве альтернативы, если ожидаемое поведение таково, что sem_init не инициализирует память sem_t и это зависит от вызывающего, то поведение определенно изменилось с обновлением RHEL 5.4
pxb
- вот код тестового примера на случай, если кто-то еще захочет попробовать. Обратите внимание, что проблема возникает только тогда, когда sem_timedwait вызывается из .so, и только RHEL5.4 (возможно, 5.3 не тестировал его), и только когда он построен как 32-битный двоичный файл (конечно, с привязкой к 32-битным библиотекам)
1) в 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) в main.cpp (обратите внимание на дублирующую тестовую функцию, чтобы мы могли сравнить выполнение из .so с в exe)
#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) здесь '