我只是花了几天的时间来寻找一个错误,该错误是由于对:: CreateMutex()的调用失败而引发未处理的异常而导致的。请记住CreateMutex()
,不要试图打开互斥锁,而只是打开一个手柄。即使互斥锁已经存在,它也不会失败,至少只要我将bInitialOwner设置为FALSE即可。
但是,如果我::CreateMutexA(0, 0, "testtesttest123");
从Windows服务(w3wp.exe
是其父级,scvhost.exe
是其祖父级,并且在IIS APPPOOL\Worker1
用户帐户下运行)产生的程序中调用,则它将失败,并且如果互斥体已经由在其下运行的另一个进程创建,则返回NULL。IIS APPPOOL\*
。
我创建了一个最小的示例来重现此问题:
void main()
{
HANDLE handle = CreateMutexA(0, 0, "testtesttest123");
std::string lastError = MyGetLastErrorAsText();
MyAppendToLog("%p %s\n", handle, lastError.c_str());
Sleep(INFINITE);
}
我通过从资源管理器(普通用户帐户)双击两次来运行可执行文件,然后使它由Windows服务生成,然后再次从资源管理器运行它。
这将创建以下日志:
C:\ Test \ ReproduceMutexCrash.exe:00000034错误_成功 C:\ Test \ ReproduceMutexCrash.exe:00000034 ERROR_ALREADY_EXISTS c:\ inetpub \ wwwroot \ Worker1 \ ReproduceMutexCrash.exe:00000034 错误00000000 ERROR_ACCESS_DENIED C:\ Test \ ReproduceMutexCrash.exe:00000034 ERROR_ALREADY_EXISTS
这里的IIS APPPOOL\Worker1
Worker1在下运行,而Worker2在IIS APPPOOL\Worker2
用户帐户下运行。
从日志中可以明显看出,如果互斥锁是由普通用户进程创建的,则这并不会阻止其他用户进程甚至Windows Service打开句柄。但是,如果Windows服务已创建了互斥锁,则::CreateMutex()
尽管其他用户进程仍可以毫无障碍地打开句柄,但在被另一个Windows服务调用时失败。
有谁知道为什么会这样吗?
编辑:我看到互斥对象是\Sessions\1\BaseNamedObjects\testtesttest123
资源管理器生成该进程的时间,而\BaseNamedObjects\testtesttest123
该进程是由创建的IIS
,所有者是Worker1
(首先设法创建互斥量的进程)。
多亏了评论的帮助,我终于弄清了为什么会发生这种情况。确实是由于权限,并且因为进程是从不同的用户帐户运行的。我通过运行2个单独的进程(但使用相同的用户帐户-)验证了这一点IIS APPPOOL\Worker1
,并且两个进程都::CreateMutex()
有效并返回了有效的HANDLE。
仅当互斥锁已被其下IIS APPPOOL\Worker1
的进程锁定并且正在IIS APPPOOL\Worker2
尝试访问它的进程时,它才会失败。
另外,我尝试通过创建一个空的DACL创建没有任何安全性的互斥体:
SECURITY_ATTRIBUTES sa = { sizeof(sa) };
SECURITY_DESCRIPTOR SD;
InitializeSecurityDescriptor(&SD, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&SD, TRUE, NULL, FALSE);
sa.lpSecurityDescriptor = &SD;
HANDLE mutex = CreateMutexA(&sa, 0, "testtesttest123");
使用空的DACL,来自不同用户帐户的2个进程可以打开相同的互斥锁。
另外,由用户进程创建的互斥锁未引起ERROR_ACCESS_DENIED的原因是因为它在不同的范围内创建了互斥锁- \Sessions\1\BaseNamedObjects\testtesttest123
,因此没有权限冲突,因为Web服务进程正在以下位置创建新的互斥锁\BaseNamedObjects\testtesttest123
,因此他们无论如何都不会访问相同的对象。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句