Я использую pthreads в приложении Windows. Я заметил, что моя программа зашла в тупик - быстрая проверка показала, что произошло следующее:
Нить 1 порождала Нить 2. Нить 2 порождала Нить 3. Нить 2 ожидала мьютекс из Нити 3, которая не была разблокирована.
Итак, я пошел отлаживать в GDB и получил следующее при возврате третьего потока:
Thread 3 (thread 3456.0x880):
#0 0x7c8106e9 in KERNEL32!CreateThread ()
from /cygdrive/c/WINDOWS/system32/kernel32.dll
Cannot access memory at address 0x131
Он как-то застрял, заблокирован в функции Windows CreateThread! Очевидно, что он не мог разблокировать мьютекс, когда он даже не мог начать выполнять код. Тем не менее, несмотря на то, что он явно застрял здесь, pthread_create вернул ноль (успех).
Что делает это особенно странным, так это то, что у того же приложения в Linux таких проблем нет. Что в мире может привести к зависанию потока в процессе создания (!?), Но успешному возвращению, как если бы он был создан правильно?
Редактировать: в ответ на запрос кода вот некоторый код (упрощенно):
Создание темы:
if ( pthread_create( &h->lookahead->thread_handle, NULL, (void *)lookahead_thread, (void *)h->thread[h->param.i_threads] ) )
{
log( LOG_ERROR, "failed to create lookahead thread\n");
return ERROR;
}
while ( !h_lookahead->b_thread_active )
usleep(100);
return SUCCESS;
Обратите внимание, что ждет, пока b_thread_active не будет установлен , поэтому каким-то образом устанавливается b_thread_active, поэтому вызываемый поток должен что-то сделать ...
... вот функция lookahead_thread:
void lookahead_thread( mainstruct *h )
{
h->lookahead->b_thread_active = 1;
while( !h->lookahead->b_exit_thread && h->lookahead->b_thread_active )
{
if ( synch_frame_list_get_size( &h->lookahead->next ) > delay )
_lookahead_slicetype_decide (h);
else
usleep(100); // Arbitrary number to keep thread from spinning
}
while ( synch_frame_list_get_size( &h->lookahead->next ) )
_lookahead_slicetype_decide (h);
h->lookahead->b_thread_active = 0;
}
lookahead_slicetype_decide (h); это то, что делает поток.
Мьютекс, synch_frame_list_get_size:
int synch_frame_list_get_size( synch_frame_list_t *slist )
{
int fno = 0;
pthread_mutex_lock( &slist->mutex );
while (slist->list[fno]) fno++;
pthread_mutex_unlock( &slist->mutex );
return fno;
}
Обратный след нити 2:
Thread 2 (thread 332.0xf18):
#0 0x00478853 in pthread_mutex_lock ()
#1 0x004362e8 in synch_frame_list_get_size (slist=0x3ef3a8)
at common/frame.c:1078
#2 0x004399e0 in lookahead_thread (h=0xd33150)
at encoder/lookahead.c:288
#3 0x0047c5ed in ptw32_threadStart@4 ()
#4 0x77c3a3b0 in msvcrt!_endthreadex ()
from /cygdrive/c/WINDOWS/system32/msvcrt.dll
#5 0x7c80b713 in KERNEL32!GetModuleFileNameA ()
from /cygdrive/c/WINDOWS/system32/kernel32.dll
#6 0x00000000 in ??