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

Windows Discussion :

[Mutex] Comment faire des mutex non réentrants ?


Sujet :

Windows

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    228
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 228
    Points : 102
    Points
    102
    Par défaut [Mutex] Comment faire des mutex non réentrants ?
    Question simple,

    Comment puis je faire des mutex non réentrant sous Windows ?
    C'est à dire avoir le même fonctionnement que des mutex linux (posix ?)
    J'ai eu brau chercher sur la MSDN et ici mais pas moyen de trouver une réponse satisfaisante

  2. #2
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Je ne connais pas assez le fonctionnement des mutex linux.
    Qu'est supposée faire la non-réentrance d'un mutex ?
    Que doit-il se passer si un thread tente de verrouiller un mutex qu'il possède déjà ? (parce que pour moi, c'est ça la réentrance ou non d'un mutex).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    228
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 228
    Points : 102
    Points
    102
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Je ne connais pas assez le fonctionnement des mutex linux.
    Qu'est supposée faire la non-réentrance d'un mutex ?
    Que doit-il se passer si un thread tente de verrouiller un mutex qu'il possède déjà ? (parce que pour moi, c'est ça la réentrance ou non d'un mutex).
    Sous linux si tu fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ...
    getmutex(A)
    print("toto);
    getmutex(A);
    print("titi");
    ...
    Tu ne verras jamais ce bon vieux titi, par contre sous Windows oui.
    De base les mutex linux ne sont pas réentrant il faut les configurer pour qu'il le devienne (et ce n'est pas possible sur tous les systems) alors que de ce que j'ai vu jusqu'à maintenant les mutex (et aussi les sections critiques) windows sont réentrant et je n'arrive pas à les faire devenir non réentrants

  4. #4
    Membre émérite Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Points : 2 280
    Points
    2 280
    Par défaut
    A ma connaissance c'est impossible car c'est le comportement normal et particuliers des mutex. En revanche tu peux utiliser les fast mutex qui eux répondent à tes exigences, voire la fonction ExAcquireFastMutex().
    Cordialement.
    "The quieter you become, the more you are able to hear"
    "Plus vous êtes silencieux, plus vous êtes capable d'entendre"

  5. #5
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par chronos Voir le message
    Sous linux si tu fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ...
    getmutex(A)
    print("toto);
    getmutex(A);
    print("titi");
    ...
    Tu ne verras jamais ce bon vieux titi
    Euh... Et à quoi ça sert ?
    Si ça deadlocke, ça plante complètement:
    • le thread,
    • et tout le processus puisque le thread ne pourra jamais libérer le mutex.

    Encore, si le second getmutex() provoquait la levée d'une exception/d'un signal, je comprendrais. Mais s'il s'agit simplement de bloquer, ça donne une Étreinte Fatale et ça ne sert absolument à rien...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  6. #6
    Rédacteur
    Avatar de Neitsa
    Homme Profil pro
    Chercheur sécurité informatique
    Inscrit en
    Octobre 2003
    Messages
    1 041
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Chercheur sécurité informatique

    Informations forums :
    Inscription : Octobre 2003
    Messages : 1 041
    Points : 1 956
    Points
    1 956
    Par défaut
    Bonjour,

    De plus je ne comprend pas l'intérêt d'un mutex dans le même thread. On utilise au moins deux threads pour gérer un accès concurrent au même objet.

    Code C : 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
     
    #include <windows.h>
    #include <stdio.h>
    #include <stdlib.h>
     
    DWORD WINAPI SecondThread( LPVOID lpParam ) ;
     
    int main (void)
    {
    	HANDLE hMutex = NULL, hThread = NULL;
    	DWORD err;
     
    	hMutex = CreateMutex(NULL, TRUE, TEXT("Mutex1"));
    	if(hMutex == NULL)
    	{
    		printf("Can't create mutex\n");
    		return -1;
    	}
     
    	err = GetLastError();
    	if(err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED)
    		printf("Mutex already exists or access to mutex is denied !\n");
    	else
    		printf("Mutex created successfully\n");
     
    	hThread = CreateThread(NULL, 0, SecondThread, NULL, 0, NULL);
    	if(hThread == NULL)
    		printf("Can't create thread.\n");
    	else
    		printf("Thread created.\n");
     
    	Sleep(1000);
     
    	return 0;
    }
    DWORD WINAPI SecondThread( LPVOID lpParam ) 
    { 
    	HANDLE hMutex = NULL;
    	DWORD err;
     
    	printf("In the 2nd thread.\n");
     
    	hMutex = CreateMutex(NULL, TRUE, TEXT("Mutex1"));
    	if(hMutex == NULL)
    	{
    		printf("Can't create mutex\n");
    		return -1;
    	}
     
    	err = GetLastError();
    	if(err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED)
    		printf("Mutex already exists or access to mutex is denied !\n");
    	else
    		printf("Mutex created successfully.\n");
     
        return 0; 
    }

    Output :

    Mutex created successfully
    Thread created.
    In the 2nd thread.
    Mutex already exists or access to mutex is denied !

  7. #7
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    La réservation du mutex dans le même thread est généralement due à une erreur de réentrance accidentelle.

    Le P.O. veut donc pouvoir empêcher cela, mais pour moi, empêcher cela par un deadlock non-récupérable, c'est un remède pire que la maladie.

    Pour moi, le plus simple est d'ajouter à la variable à protéger un booléen qu'on règle dès qu'on a le mutex et qu'on annule dès qu'on ne l'a plus, et lors de l'acquisition du mutex, vérifier qu'on ne l'a pas déjà et retourner une erreur dans ce cas...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Un code de ce genre-là devrait aider...
    Code C : 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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    typedef enum e_mutexResult
    {
    	Mu_OK = 0,
    	Mu_LOCKED = -1000,
    	Mu_REENTRANCY,
    	Mu_CREATE_FAILED,
    	Mu_WAS_ABANDONED,
    	Mu_UNEXPECTED,
     
    	Mu_Max
    } MuRESULT;
     
    typedef struct s_nonReentrantMutex
    {
    	HANDLE hMutex;
    	BOOL bLocked;
    } NRMUTEX;
     
    MuRESULT InitializeNRMutex(NRMUTEX*pMu)
    {
    	...
    }
     
    MuRESULT ClearNRMutex(NRMUTEX*pMu)
    {
    	...
    }
     
    MuRESULT LockNRMutex(NRMUTEX*pMu)
    {
    	DWORD res = WaitForSingleObject(pMu->hMutex, INFINITE);
    	if(res == WAIT_ABANDONED_0)
    	{
    		ReleaseMutex(pMu->hMutex);
    		return Mu_WAS_ABANDONED;
    	}
    	if(res != WAIT_OBJECT_0)
    		return Mu_UNEXPECTED;
     
    	//Vérifier la réentrance
    	if(pMu->bLocked)
    	{
    		ReleaseMutex(pMu->hMutex);
    		return Mu_REENTRANCY;
    	}
    	pMu->bLocked = TRUE;
    	return Mu_OK;
    }
     
    MuRESULT UnlockNRMutex(NRMUTEX*pMu)
    {
    	assert(pMu->bLocked);
    	pMu->bLocked = FALSE;
    	if(!ReleaseMutex(pMu->hMutex))
    		return Mu_UNEXPECTED;
    	return Mu_OK;
    }

    PS: Bien sûr, on peut aussi utiliser une CRITICAL_SECTION au lieu d'un mutex...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  9. #9
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    228
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 228
    Points : 102
    Points
    102
    Par défaut .
    Il n'y à evidement aucun interet a faire deux demandes de mutex, avoir un comportement non réentrant est simplement la pour coller au comportement linux. Le code que j'ecris est sensé être portable, pour le moment j'ai ecrit les choses sous Windows et evidement j'ai des functions protégées via des CS pour le moment maisa en passant sous linux on arrive à des deadlock parcque un thread s'auto block sur un mutex qu'il possède déjà.

    Donc pour être plus efficace en terme de debug je cherche à avoir le même comportement entre linux windows, vous l'avez tous souligné. L'acquisition "double" de mutex est un problème mais pour le résoudre encore faut il pouvoir le voir ! Et sous windows, je n'ai pas trouvé de moyen de le faire

    [Edit]
    Je vais voir si je peux appliquer ta solution Medinoc mais ça me parait bien compliquer pour pas grand chose
    Mes mutex sont cahés par une couche d'abstarction qui gère un pool d'objet histoire d'avoir les mêmes interfaces quelque soit le system...

    Vais voir aussi du côté fast mutex

  10. #10
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le truc que j'ai posté devrait t'y aider.
    Et si tu ne veux pas retourner une variable d'état, tu peux toujours lancer une exception C++ ou une exception SEH quand tu détectes une double acquisition...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  11. #11
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    228
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 228
    Points : 102
    Points
    102
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Le truc que j'ai posté devrait t'y aider.
    Et si tu ne veux pas retourner une variable d'état, tu peux toujours lancer une exception C++ ou une exception SEH quand tu détectes une double acquisition...
    Je fait du C mais je vais tester quelque chose du genre merci

  12. #12
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Citation Envoyé par chronos Voir le message
    Mes mutex sont cahés par une couche d'abstarction qui gère un pool d'objet histoire d'avoir les mêmes interfaces quelque soit le system...
    Ce qui est une bonne chose pour toi: Plutôt que de changer les appels, il te suffit de tripoter la couche d'abstraction...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Comment faire des etats pour une application web ?
    Par ovh dans le forum Autres outils décisionnels
    Réponses: 6
    Dernier message: 06/07/2021, 03h25
  2. Réponses: 13
    Dernier message: 21/09/2007, 20h57
  3. Comment faire un panel non rectangulaire?
    Par grincheux dans le forum C++Builder
    Réponses: 4
    Dernier message: 11/05/2003, 15h47
  4. [VB6][impression]Comment faire des effets sur les polices ?
    Par le.dod dans le forum VB 6 et antérieur
    Réponses: 11
    Dernier message: 08/11/2002, 10h31
  5. Réponses: 8
    Dernier message: 18/09/2002, 03h20

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