###環境
Windows 10 Home
Microsoft Visual C++ 2010 Express
###発生している問題・エラーメッセージ
同じログオンセッション内で Global\ プリフィクスのミューテックスを複数作成できるのに、異なるログオンセッションで複数作成しようとすると失敗してしまいます。(2つ目のCreateMutexAがNULLを返します)
###試したこと
ミューテックスによるプロセス間の排他制御を実現するため(方法を確認するため)、
以下のソースファイル Mutex.c を作成し、cl Mutex.c でビルドした Mutex.exe でテストを行いました。
C
1#include <stdio.h> 2#include <conio.h> 3#include <stdlib.h> 4#include <windows.h> 5 6int main(int argc, char **argv) 7{ 8 char *name; 9 HANDLE hdl; 10 int ret; 11 12 if(argc != 2) 13 return; 14 15 name = argv[1]; 16 printf("name == '%s'\n", name); 17 18 hdl = CreateMutexA(NULL, FALSE, name); 19 printf("hdl == %d\n", (int)hdl); 20 21 if(hdl == NULL) 22 return; 23 24 printf("LOCKING...\n"); 25 ret = WaitForSingleObject((HANDLE)hdl, INFINITE); 26 27 if(ret != WAIT_OBJECT_0) 28 return; // fatal 29 30 printf("LOCKED\n"); 31 32 _getch(); 33 34 ReleaseMutex(hdl); 35 CloseHandle(hdl); 36 printf("RELEASE & CLOSED\n"); 37}
2つコンソール(cmd.exe)を開き、それぞれで Mutex Global\aaa を実行したところ、以下のとおり期待通り動きました。
- 先に起動した方が LOCKED まで表示され、後に起動した方が LOCKING... まで表示される。
- 先に起動した方のコンソールで何かキーを押す。
- 先に起動した方が RELEASE & CLOSED を表示して終了し、後に起動した方が LOCKED まで表示される。
- 後に起動した方のコンソールで何かキーを押す。
- 後に起動した方が RELEASE & CLOSED を表示して終了する。
ですが、2ユーザーでログオンし(それぞれt,rとします)それぞれのログオンセッションで Mutex Global\aaa を実行すると以下のようになってしまいます。
- tユーザーのデスクトップ画面を表示し、
- コンソール(cmd.exe)を開き、Mutex Global\aaa を実行する。
- LOCKED まで表示される。
- ユーザーの切り替えを行いrユーザーのデスクトップ画面を表示する。
- コンソール(cmd.exe)を開き、Mutex Global\aaa を実行する。
- hdl == 0 が表示され終了してしまう。
6 において LOCKING... まで進むことを期待していたのですが、CreateMutexA がミューテックスハンドルを返さず NULL を返してきます。
CreateMutexA の使い方(引数の指定)に間違いがあるのではないかと考えています。
CreateMutexA の正しい使い方、あるいは↑のソース上の間違いをご指摘願います。
###C#の場合はうまくいった
なお、C#でも同様の問題が発生しましたが、以下URLのコードを試したところ解決しました。
http://qiita.com/hanishi@github/items/f2597dc4a351bc1f9795
なので、このコード中の
C#
1var allowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow); 2var securitySettings = new MutexSecurity(); 3securitySettings.AddAccessRule(allowEveryoneRule); 4mutex.SetAccessControl(securitySettings);
と同じことをやれば良いのではないかと思うのですが、Cでのやり方が見えていない状態です。
そもそも何故異なるログオンセッションで同じ名前のミューテックスを生成出来ないのでしょうか...
その理由もお教えいただけると幸いです。
よろしくお願いします。
解決しました
ご回答いただいた内容を元に以下の通り修正したところ、うまくいきました。
ありがとうございます。
C
1#pragma comment(lib, "advapi32.lib") 2 3#include <stdio.h> 4#include <conio.h> 5#include <stdlib.h> 6#include <windows.h> 7#include <winbase.h> 8 9int main(int argc, char **argv) 10{ 11 char *name; 12 HANDLE hdl; 13 int ret; 14 15 if(argc != 2) 16 return; 17 18 name = argv[1]; 19 printf("name == '%s'\n", name); 20 21 { 22 SECURITY_DESCRIPTOR sd; 23 SECURITY_ATTRIBUTES secAttribute; 24 InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); 25 SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE); 26 secAttribute.nLength = sizeof(secAttribute); 27 secAttribute.lpSecurityDescriptor = &sd; 28 secAttribute.bInheritHandle = TRUE; 29 hdl = CreateMutexA(&secAttribute, FALSE, name); 30 } 31 32 printf("hdl == %d\n", (int)hdl); 33 34 if(hdl == NULL) 35 return; 36 37// _getch(); 38 39 printf("LOCKING...\n"); 40 ret = WaitForSingleObject((HANDLE)hdl, INFINITE); 41 42 if(ret != WAIT_OBJECT_0) 43 return; // fatal 44 45 printf("LOCKED\n"); 46 47 _getch(); 48 49 ReleaseMutex(hdl); 50 CloseHandle(hdl); 51 printf("RELEASE & CLOSED\n"); 52}

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2016/09/23 11:23