Bonjour tout le monde,
Je coince sur un comportement étrange de sémaphores POSIX (semaphore.h). À un moment une sémaphore (queue3->full plus bas) est en wait. Et je fais un post sur une autre sémaphore (queue1->mutex plus bas). Et ce post-là déclenche le wait de la sémaphore queue3->full !
J'ai pu isoler ce comportement en traçant tous mes appels à sem_wait et sem_post avec des #define :
L'idée de mettre le %p permet de vérifier que ce sont bien des sémaphores différentes, et pas des pointeurs de noms différents qui se seraient retrouvés à pointer au même endroit.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 #ifdef SQ_DEBUG # define sq_debug(msg...) { if (queue->debugged) \ { \ fprintf(stderr, "sq %d", queue->debugged); \ debugmsg("", msg); \ } } # define sem_post(sem) \ { \ sq_debug("post to " #sem " (%p) at line %d", sem, __LINE__); \ sem_post(sem); \ } # define sem_wait(sem) \ { \ sq_debug("wait for " #sem " (%p) at line %d", sem, __LINE__); \ sem_wait(sem); \ sq_debug("wait done for " #sem " (%p) at line %d", sem, __LINE__); \ } #else # define sq_debug(msg...) ((void) 0) #endif
Le code qui fait le sem_post(queue1->mutex) est le suivant :
Le sleep(10) sert à donner le temps à tous mes autres threads de se retrouver dans une situation bloquante, afin que leurs messages de debug ne me gênent pas.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 int sq_close(SyncQueue *queue) { int result; sem_wait(&queue->mutex); sq_debug("sq_close entered CS; size = %d", queue->size); result = !queue->closed; if (result) { queue->writercount = 0; queue->closed = true; sq_debug("closed by sq_close"); sem_post(&queue->full); } sleep(10); sq_debug("sleep(10) done"); sq_debug("sq_close exiting CS; size = %d", queue->size); sem_post(&queue->mutex); return result ? EXIT_SUCCESS : EXIT_FAILURE; }
Et le code qui fait le sem_wait(queue3->full) est le suivant :
Lorsque je lance mon programme, puis appelle sq_close(queue1), les derniers messages de debug que je reçois sont :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 int sq_dequeue(SyncQueue *queue, void **item) { SyncQueueNode *node; sem_wait(&queue->full); sem_wait(&queue->mutex); sq_debug("sq_dequeue entered CS; size = %d; closed = %d", queue->size, queue->closed); /* Closed queue */ if (queue->closed && (!queue->first)) { sq_debug("can't dequeue, the queue is closed and empty"); sem_post(&queue->mutex); sem_post(&queue->full); return EXIT_FAILURE; } assert(queue->size > 0); ... }
Notant que la queue3 bloque sur son queue->full depuis le début du programme.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 sq 1: sleep(10) done sq 1: sq_close exiting CS; size = 9 sq 1: post to &queue->mutex (0xbfb6ff9c) at line 359 sq 3: wait done for &queue->full (0xbfb70074) at line 235 sq 3: wait for &queue->mutex (0xbfb70094) at line 236 sq 3: wait done for &queue->mutex (0xbfb70094) at line 236 sq 3: sq_dequeue entered CS; size = 0; closed = 0 tracesweb: syncqueue.c:252: sq_dequeue: Assertion `queue->size > 0' failed. Abandon
Je ne parviens vraiment pas à m'expliquer commant le sem_post(queue1->mutex) libère le sem_wait(queue3->full)
Est-ce que quelqu'un aurait une idée d'explication ? Parce que, là, ça me fout en l'air tout mon programme
Edit : avant que vous ne posiez la question : je développe sous Linux et Solaris (même problème des deux côtés). Et oui, j'ai bien fait sem_init sur toutes mes sémaphores avant de les utiliser.
d'avance
Partager