IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

POSIX C Discussion :

[Sémaphores] Comportement étrange : post sur l'un déclenche le wait d'un autre


Sujet :

POSIX C

  1. #1
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 152
    Points
    10 152
    Par défaut [Sémaphores] Comportement étrange : post sur l'un déclenche le wait d'un autre
    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 :
    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
    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.

    Le code qui fait le sem_post(queue1->mutex) est le suivant :
    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;
    }
    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.

    Et le code qui fait le sem_wait(queue3->full) est le suivant :
    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);
     
        ...
    }
    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
    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
    Notant que la queue3 bloque sur son queue->full depuis le début du programme.

    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
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

  2. #2
    Expert éminent sénior

    Avatar de sjrd
    Homme Profil pro
    Directeur de projet
    Inscrit en
    Juin 2004
    Messages
    4 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : Suisse

    Informations professionnelles :
    Activité : Directeur de projet
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2004
    Messages : 4 517
    Points : 10 152
    Points
    10 152
    Par défaut
    Eh bien finalement j'ai trouvé

    En fait ce n'était pas le sem_post(&queue1->mutex) qui libérait le sem_wait(&queue3->full), ce qui est évidemment totalement inimaginable. Mais en fait, il se trouve que le sem_post était une des dernières actions d'un gestionnaire de signal. Et que c'est la fin du gestionnaire de signal qui libérait le sem_wait(), mais avec un code d'erreur EINTR.

    Moralité : quand on a déjà lu 10 fois la page de manuel sans trouver d'explications, il faut la relire une 11ème fois : on finit par trouver
    sjrd, ancien rédacteur/modérateur Delphi.
    Auteur de Scala.js, le compilateur de Scala vers JavaScript, et directeur technique du Scala Center à l'EPFL.
    Découvrez Mes tutoriels.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Comportement étrange boucle sur éléments
    Par laloune dans le forum jQuery
    Réponses: 1
    Dernier message: 24/09/2014, 10h46
  2. Comportement étrange sur un bulleted list
    Par stroumfs dans le forum ASP.NET
    Réponses: 1
    Dernier message: 14/10/2008, 15h51
  3. [2.0] comportement étrange sur condition sur string.indexOf
    Par franculo_caoulene dans le forum VB.NET
    Réponses: 26
    Dernier message: 18/06/2008, 12h09
  4. Comportement étrange ksh sur linux
    Par hugo123 dans le forum Shell et commandes GNU
    Réponses: 6
    Dernier message: 09/08/2006, 10h55
  5. Formulaire au comportement étrange : problème de POST
    Par Chlipouni dans le forum Langage
    Réponses: 6
    Dernier message: 18/07/2006, 11h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo