Dostaję błąd segmentacji podczas dołączania do wątku podrzędnego i wyczerpałem wszystkie opcje, które mogłem pomyśleć o debugowaniu, patrząc na Stack-overflow i resztę Internetu! :) Będę tak dokładny jak tylko będę mógł . Kod jest napisany w C++ i skompilowany z GNU GCC na OSX 10.6.8. Połączyłem bibliotekę "pthread", używając parametru "-pthread". Próbowałem również "-lphtread". Bez różnicy.pthread_join zawiesza się sporadycznie z błędem segmentacji na OSX
Używam następujące zmienne globalne:
pthread_t gTid;
pthread_attr_t gAttr;
int gExitThread = 0;
Tworzę wątek dziecko z moim głównym wątku wykonania:
err = pthread_attr_init(&gAttr);
if (err)
{
throw CONTROLLER_THREAD_ERROR;
}
err = pthread_attr_setdetachstate(&gAttr, PTHREAD_CREATE_JOINABLE);
if (err)
{
throw CONTROLLER_THREAD_ERROR;
}
err = pthread_create(&gTid,&gAttr,threadHandler,NULL);
if (err)
{
throw CONTROLLER_THREAD_ERROR;
}
wewnątrz „threadHandler”, mam następujący uruchom pętlę za pomocą interfejsu API podstawy:
// Enter run loop
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, RUN_LOOP_TIMEOUT, false);
while (result == kCFRunLoopRunTimedOut)
{
if (gExitThread) break;
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, RUN_LOOP_TIMEOUT, false);
}
Używana jest zmienna globalna gExitThread sygnalizować, że wątek powinien samoczynnie zabić. Makro RUN_LOOP_TIMEOUT jest ustawione na 2 sekundy (chociaż większe i mniejsze wartości nie mają znaczenia).
Nić jest sygnalizowane zostać zabity przez następujący fragment kodu w głównym wątku:
int err = 0;
void* exitValue = NULL;
printf("Stopping controller thread...\n");
gExitThread = 1;
err = pthread_join(gTid, &exitValue);
if (err)
{
displayError2(err);
throw CONTROLLER_THREAD_ERROR;
}
err = pthread_attr_destroy(&gAttr);
if (err)
{
throw CONTROLLER_THREAD_ERROR;
}
Wezwanie do „pthread_join” wywala z winy segmentacji po krótkiej przerwie. Zauważyłem również, że zastąpienie wywołania "pthread_join" normalnym snem, powiedzmy dwie sekundy, powoduje dokładnie ten sam błąd segmentacji podczas wykonywania "usleep (2000000)"! Skopiuję z powrotem ślad zrzutu pamięci poniżej dla "pthread_join" i "usleep".
pthread_join:
#0 0x00007fff8343aa6a in __semwait_signal()
#1 0x00007fff83461896 in pthread_join()
#2 0x000000010000179d in Controller::cleanup() at src/native/osx/controllers.cpp:335
#3 0x0000000100008e51 in ControllersTest::performTest (this=0x100211bf0) at unittests/src/controllers_test.cpp:70
#4 0x000000010000e5b9 in main (argc=2, argv=0x7fff5fbff980) at unittests/src/verify.cpp:34
usleep (2000000):
#0 0x00007fff8343aa6a in __semwait_signal()
#1 0x00007fff8343a8f9 in nanosleep()
#2 0x00007fff8343a863 in usleep()
#3 0x000000010000177b in Controller::cleanup() at src/native/osx/controllers.cpp:335
#4 0x0000000100008e3d in ControllersTest::performTest (this=0x100211bf0) at unittests/src/controllers_test.cpp:70
#5 0x000000010000e5a5 in main (argc=2, argv=0x7fff5fbff980) at unittests/src/verify.cpp:34
Każda pomoc będzie mile widziana.
Dziękuję Milan. To było dokładnie to! Okazuje się, że w moim wątku rzutowałem wskaźnik NULL na typ klasy, a następnie rozbiłem się podczas uzyskiwania dostępu do elementów danych tej instancji. Nie tylko jest to naprawione, wiem trochę więcej o wątkach i gdb :) – lawrenceB