Schließlich herausgefunden, was das Problem ist. Auf RHEL 5.4, wenn wir sem_init aufrufen, dann sem_timedwait, erhalten wir ein zufälliges Verhalten des zeitgesteuerten Wartens, abhängig davon, wo sich der Code befindet, ob das Objekt, das sem_t besitzt, auf dem Heap oder Stack ist. Manchmal kehrt die zeitgesteuerte Wartezeit sofort zurück mit errno = 38 (ENOSYS), manchmal wartet es richtig, bevor es zurückkehrt.
es über valgrind Lauf gibt diesen Fehler:
==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)
Wenn ich genau den gleichen Code ausführen auf RHEL 5.2 das Problem verschwindet und valgrind Berichte keine Fehler.
Wenn ich ein memset auf der sem_t Variable vor sem_init Aufruf des Problems auf RHEL weggeht 5,4
memset(&_semaphore, 0, sizeof(sem_t));
Also, es sieht aus wie ein Bug mit Semaphore auf RHEL5.4 oder etwas eingeführt wurde, dass es verwendet intern, und sem_init initialisiert den sem_t-Speicher nicht korrekt. Oder das sem_timed-Warten hat sich verändert, um auf eine Weise sensibel zu sein, wie es vorher nicht war.
Interessanterweise gibt sem_init in keinem Fall einen Fehler zurück, um anzuzeigen, dass es nicht funktioniert hat.
Alternativ kann, wenn das erwartete Verhalten ist, dass sem_init nicht die Erinnerung an sem_t intialise wird, und das ist bis zu dem Anrufer, dann hat sich das Verhalten sicherlich mit RHEL 5.4
geändert
PXB
Update - hier ist der Test-Case-Code, falls jemand anderes es versuchen möchte. Beachten Sie, dass das Problem nur auftritt, wenn sem_timedwait von einem .so aufgerufen wird, und nur RHEL5.4 (vielleicht 5.3 hat es nicht getestet) und nur als 32-Bit-Binärcode (gegen 32-Bit-Bibliotheken natürlich)
1) in 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) in main.cpp (man beachte die doppelte Testfunktion so können wir aus dem .so mit der 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 laufen vergleichen) hier ist das Makefile
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
Die Testfälle sind:
- Lauf aus .so ohne Memset ohne dabei Memset
- laufen
- Lauf aus .so und tun Memset
- Lauf aus exe zu tun aus innerhalb exe und do
memset und hier läuft das Ergebnis auf 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
Sie können diesen Fall 1 kehrt sofort mit errno siehe = 38.
Wenn wir den exakt gleichen Code auf RHEL5.2 laufen bekommen wir folgendes:
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
können Sie sehen, dass Alle Fälle funktionieren jetzt wie erwartet!
Managed, um es zu beheben, aber ich bin mir nicht sicher, wie der Fix funktioniert. Der Code, der die Semaphorfunktionen aufruft, befand sich in einer Klasse innerhalb eines .so, und diese wurden wiederum von der ausführbaren Datei selbst aufgerufen. Wenn wir den Code aus der cpp-Datei in den Header verschieben (dh die Klasse effektiv in die ausführbare Datei einfügen), verschwindet das Problem. so scheint es zu sein: auf RHEL5.4 wenn wir die sem_timedwait von innerhalb der .so es schlägt fehl, aber wenn wir den gleichen Aufruf von der ausführbaren Datei es funktioniert. Und ich habe keine Ahnung, warum ... – pxb