pthread_join периодически вылетает из-за ошибки сегментации в OSX - PullRequest
5 голосов
/ 07 октября 2011

Я получаю ошибку сегментации при присоединении к дочернему потоку, и я исчерпал все возможные варианты отладки, просмотра переполнения стека и остального Интернета! :) Я буду так тщательно, как я могу. Код написан на C ++ и скомпилирован с GNU GCC на OSX 10.6.8. Я связал библиотеку pthread с помощью параметра -pthread. Я также попробовал '-lphtread'. Без разницы.

Я использую следующие глобальные переменные:

pthread_t gTid;

pthread_attr_t gAttr;

int gExitThread = 0;

Я создаю дочерний поток из основного потока выполнения:

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;
}

Внутри threadHandler у меня есть следующий цикл выполнения с использованием базового API:

// Enter run loop
result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, RUN_LOOP_TIMEOUT, false);
while (result == kCFRunLoopRunTimedOut)
{
    if (gExitThread) break;
    result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, RUN_LOOP_TIMEOUT, false);
}

Глобальная переменная gExitThread используется для указания того, что поток должен корректно завершить работу. сам. Макрос RUN_LOOP_TIMEOUT установлен на 2 секунды (хотя большие и меньшие значения не имеют значения).

Поток сигнализируется на удаление следующим фрагментом кода в основном потоке:

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;
}

Вызов pthread_join завершается с ошибкой сегментации после небольшой задержки. Я также заметил, что замена вызова pthread_join обычным сном, скажем, на две секунды, вызывает точно такую ​​же ошибку сегментации при выполнении usleep (2000000)! Я скопирую обратную трассировку дампа ядра ниже как для pthread_join, так и для 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

Любая помощь будет принята с благодарностью.

1 Ответ

8 голосов
/ 07 октября 2011

Кажется, что код после цикла while внутри threadHandler вызывает ошибку segfault.Если сигнал генерируется (например, SIGSEGV) внутри потока, сам процесс будет убит.

Попробуйте использовать GDB и thread apply all bt, чтобы получить обратную трассировку для всех потоков.

...