J'utilise pthreads dans une application Windows. J'ai remarqué que mon programme était dans l'impasse - une inspection rapide a montré que ce qui suit avait eu lieu:Deadlocks avec pthreads et CreateThread
Fil 1 fils engendré 2. Fil 2 fils engendré 3. Fil 2 attendu sur un mutex du Fil 3, qui ne se déverrouillait pas.
Alors, je suis allé à déboguer dans gdb et a obtenu les points suivants lors du troisième fil tracé rétrograde:
Thread 3 (thread 3456.0x880):
#0 0x7c8106e9 in KERNEL32!CreateThread()
from /cygdrive/c/WINDOWS/system32/kernel32.dll
Cannot access memory at address 0x131
Il était coincé, dans une impasse, en quelque sorte, dans la fonction Windows CreateThread! Évidemment, il ne pouvait pas déverrouiller le mutex lorsqu'il n'était même pas capable de commencer à exécuter du code. Pourtant, malgré le fait qu'il était apparemment bloqué ici, pthread_create retourné zéro (succès).
Ce qui rend cela particulièrement étrange, c'est que la même application sous Linux n'a pas de tels problèmes. Qu'est-ce qui dans le monde provoquerait un fil à suspendre pendant le processus de création (!?) Mais retournerait avec succès comme s'il avait été créé correctement?
Edit: en réponse à la demande de code, voici un code (simplifié):
La création du fil:
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;
Notez qu'il attend que b_thread_active est réglé, donc en quelque sorte b_thread_active est en cours de définition, donc le thread appelé doit avoir fait quelque chose ...
... voici la fonction 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); est la chose que fait le fil.
Le mutex, 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;
}
Le backtrace de fil 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[email protected]()
#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 ??
utilisez-vous des attributs lorsque vous créez les threads? –
Non, aucun attribut du tout (pointeur NULL passé pour les attributs). –