2009-02-19 3 views
4

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 ?? 
+0

utilisez-vous des attributs lorsque vous créez les threads? –

+0

Non, aucun attribut du tout (pointeur NULL passé pour les attributs). –

Répondre

1

Je voudrais essayer un double contrôle votre mutex en fil 2 et 3. Pthreads fil sont mises en œuvre pour les fenêtres à l'aide de la fenêtres standard api; Il y aura donc de légères différences entre les versions Windows et Linux. C'est un problème bizarre, mais là encore, cela arrive beaucoup dans le filetage.

Pourriez-vous essayer de publier un extrait du code où le verrouillage est fait dans le thread 2, et dans la fonction dans laquelle le thread 3 devrait commencer?

Modifier en réponse à coder

vous avez fait débloquez jamais le mutex fil 2? Votre trace montre le verrouillage d'un mutex, puis la création d'un thread pour faire tout ce travail qui tente de également verrouiller sur le mutex. Je suppose que le thread 2 retourne SUCESS? En outre, pourquoi utilisez-vous des drapeaux et en dormant, peut-être que les barrières ou les variables conditionnelles pour la synchronisation des processus peuvent être plus robustes.

Une autre remarque, l'indicateur b_thread_active est-il marqué comme volatile? Peut-être que le compilateur cache quelque chose pour ne pas le laisser éclater?

+0

Ajout d'un tas de code spécifique. –

+0

Bonne prise sur le volatile - Je vais tester ça et voir si c'est le problème. Selon un autre dev gcc a une habitude de comportement incohérent en ce qui concerne les variables non-volatiles en mode threadé sur les plates-formes, ce qui pourrait entraîner le bon fonctionnement de Linux mais la rupture de Windows. –

+0

Et vous aviez raison; Alors qu'il y avait d'autres bogues dans le code, le volatile qui manquait était ce qui causait ce bug particulier. –

Questions connexes