Reputation: 337
I have 2 programs. The first program will open the second one and will also create 2 Event objects that will be used for synchronization. The second one (the one to be opened) will open those 2 Event objects. Both of the programs will run a for loop to simulate writing and reading operations from memory.
Program one:
read = CreateEvent(NULL, false, false, "READ");
write = CreateEvent(NULL, false, false, "WRITE");
CreateProcess("PATH_TO_EXE", NULL, NULL, NULL, FALSE, NULL, 0, NULL, &startupInfo, &processInformation);
for (int i = 1; i <= 100; i++)
{
printf("Wrote data to memory\n");
SetEvent(write);
WaitForSingleObject(read, INFINITE);
}
Program two:
HANDLE read, write;
read = OpenEvent(EVENT_MODIFY_STATE, false, "READ");
write = OpenEvent(EVENT_MODIFY_STATE, false, "WRITE");
for (int i = 1; i <= 100; i++)
{
WaitForSingleObject(write, INFINITE);
printf("Read data from memory.\n");
SetEvent(read);
}
I would expect the output to be:
Wrote data to memory.
Read data from memory.
Wrote data to memory.
Read data from memory.
....
but the real output is something like:
Wrote data to memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Read data from memory.
Wrote data to memory.
Read data from memory.
Wrote data to memory.
Wrote data to memory.
Read data from memory.
...
And at some point it just hangs, which would mean a deadlock. But I'm not sure how is this possible. Any help?
Upvotes: 0
Views: 393
Reputation: 33706
for WaitForSingleObject
- handle to the object (1-st parameter) must have the SYNCHRONIZE
access right. otherwise api failed with ERROR_ACCESS_DENIED
. but you call
write = OpenEvent(EVENT_MODIFY_STATE, false, "WRITE");
requested access not include SYNCHRONIZE
which you need and include EVENT_MODIFY_STATE
which you really not need in this code. so you need change code to
write = OpenEvent(SYNCHRONIZE, false, "WRITE");
also you not check result of any api call. if you do this - you just view that WaitForSingleObject(write, INFINITE);
return WAIT_FAILED
and GetLastError() == ERROR_ACCESS_DENIED
.
also if you need ipc via this 2 events with child process - better create it unnamed and inherited, and pass it values via command line to child. if you want test only event work logic - more easy use separate thread instead new process. for this test code can look like:
ULONG WINAPI child(void* p)
{
if (HANDLE read = OpenEvent(EVENT_MODIFY_STATE, false, L"READ"))
{
if (HANDLE write = OpenEvent(SYNCHRONIZE, false, L"WRITE"))
{
ULONG i = (ULONG)(ULONG_PTR)p;
do
{
if (WaitForSingleObject(write, INFINITE) == WAIT_FAILED){
DbgPrint("2:%u\n", GetLastError());
break;
}
DbgPrint("Read data from memory.\n");
if (!SetEvent(read)){
DbgPrint("3:%u\n", GetLastError());
break;
}
} while (--i);
CloseHandle(write);
}
CloseHandle(read);
}
return 0;
}
void bfg()
{
if (HANDLE read = CreateEvent(NULL, false, false, L"READ"))
{
if (HANDLE write = CreateEvent(NULL, false, false, L"WRITE"))
{
ULONG i = 16;
if (HANDLE hThread = CreateThread(0, 0, child, (PVOID)(ULONG_PTR)i, 0, 0))
{
do
{
DbgPrint("Wrote data to memory\n");
if (!SetEvent(write) || WaitForSingleObject(read, INFINITE) == WAIT_FAILED){
DbgPrint("1:%u\n", GetLastError());
break;
}
} while (--i);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
CloseHandle(write);
}
CloseHandle(read);
}
}
interesting that early (before win 8.1) was EventPair object in windows, which was design for such task. but unknown reason it was removed
Upvotes: 2