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
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
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.
Sous linux si tu fait
Tu ne verras jamais ce bon vieux titi, par contre sous Windows oui.
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"); ...
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
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"
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.
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 !
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.
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.
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
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.
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.
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager