I have this below thread function, that simply wait on two kernel objects to be signaled.
The waiting function always return WAIT_FAILED with error code 5 (access denied) and I can't tell why.
unsigned __stdcall func(void * p_this){
ReceiverThread * ThisObj = (ReceiverThread *)p_this;
HANDLE ClientsMutex = ClientsInterface::GetClientsMutex();
HANDLE WaitFor[2];
WaitFor[0] = ThisObj->PassiveEvent;
WaitFor[1] = ClientsMutex;
res = WaitForMultipleObjects(2, WaitFor, TRUE, INFINITE);
switch (res)
{
case WAIT_OBJECT_0: // both signal
if(!Clients->empty()){
dosomthing();
ReleaseMutex(ClientsMutex);
ResetEvent(WaitFor[0]);
}
break;
case WAIT_ABANDONED_0:
MessageBox(NULL, "WAIT_ABANDONED", "WAIT ERR", MB_OK);
break;
case WAIT_TIMEOUT:
MessageBox(NULL, "TimeOut !", "WAIT ERR", MB_OK);
break;
case WAIT_FAILED:
MessageBox(NULL, "Function Failure !", to_string(GetLastError()).c_str() , MB_OK);
break;
}
}
The event initialization is as follow:
PassiveEvent = CreateEvent(
NULL,
TRUE, // ResetEvent is required to set the event to non-signal state.
FALSE, // non-signaled initial state.
NULL
);
The mutex initialization is as follow:
Mutex = CreateMutex(NULL, FALSE, NULL);
I know it's little opaque, but that's all the information, maybe I'm missing something that is clear, but I can't tell why the WaitForMultipleObjects() get access denied. any ideas?
Related
I have written a Windows Service program in C++. One of the tasks it performs is to run a very large business app written in PowerBuilder. It performs a bunch of database processes and transfers data back and forth with SharePoint. The PowerBuilder app gets to a certain point where it aborts and the likely cause is because services have a limited 'desktop heap' compared to normal desktop apps.
As a test we tried using a generic service app called AlwaysUp to run the PowerBuilder app and somehow it has no problems at all. I am stumped as to why AlwaysUp has no issues. Here is the code I use to launch the PowerBuilder app:
// report running status
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus);
// run the application
event = CreateEvent(0, FALSE, FALSE, 0);
if ( CreateProcess( NULL, CommandLine, NULL, NULL, FALSE,
DETACHED_PROCESS | dwPriority, NULL,
szModule, &si, &pi ) == 0 ) {
// CreateProcess Failed
return 0;
}
// wait for either the process to end or stop event
WaitHandles[0] = pi.hProcess;
WaitHandles[1] = event;
do {
dwError = WaitForMultipleObjects(2, WaitHandles, FALSE, 60000);
switch ( dwError ) {
case WAIT_OBJECT_0:
// process ended
bRunning = FALSE;
break;
case WAIT_OBJECT_0+1:
// event triggered
bRunning = FALSE;
break;
case WAIT_TIMEOUT:
// timeout
break;
default:
// error
bRunning = FALSE;
break;
}
} while ( bRunning );
// close the handles
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
CloseHandle(event);
I'm using the following code from Microsoft as a template:
#include <windows.h>
#include <stdio.h>
#define MAX_SEM_COUNT 10
#define THREADCOUNT 12
HANDLE ghSemaphore;
DWORD WINAPI ThreadProc( LPVOID );
int main( void )
{
HANDLE aThread[THREADCOUNT];
DWORD ThreadID;
int i;
// Create a semaphore with initial and max counts of MAX_SEM_COUNT
ghSemaphore = CreateSemaphore(
NULL, // default security attributes
MAX_SEM_COUNT, // initial count
MAX_SEM_COUNT, // maximum count
NULL); // unnamed semaphore
if (ghSemaphore == NULL)
{
printf("CreateSemaphore error: %d\n", GetLastError());
return 1;
}
// Create worker threads
for( i=0; i < THREADCOUNT; i++ )
{
aThread[i] = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
if( aThread[i] == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
}
// Wait for all threads to terminate
WaitForMultipleObjects(THREADCOUNT, aThread, TRUE, INFINITE);
// Close thread and semaphore handles
for( i=0; i < THREADCOUNT; i++ )
CloseHandle(aThread[i]);
CloseHandle(ghSemaphore);
return 0;
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
And I want to adapt it so instead of being the threads the ones that determine how the semaphore fills, it's done by processes, meaning that the semaphore will fill if there are processes running and/or with any of their habdles not closes, and indeed I sort of have done it by changing the working of the thread function with this new function.
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER(lpParam);
DWORD dwWaitResult;
BOOL bContinue=TRUE;
STARTUPINFO si;
PROCESS_INFORMATION pi;
memset(&si,0,sizeof(si));
si.cb=sizeof(si);
while(bContinue)
{
// Try to enter the semaphore gate.
dwWaitResult = WaitForSingleObject(
ghSemaphore, // handle to semaphore
0L); // zero-second time-out interval
CreateProcess("arbol.exe",NULL,NULL,NULL,0,0,NULL,NULL,&si,&pi);
WaitForSingleObject(pi.hProcess,INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
switch (dwWaitResult)
{
// The semaphore object was signaled.
case WAIT_OBJECT_0:
// TODO: Perform task
printf("Thread %d: wait succeeded\n", GetCurrentThreadId());
bContinue=FALSE;
// Simulate thread spending time on task
Sleep(5);
// Release the semaphore when task is finished
if (!ReleaseSemaphore(
ghSemaphore, // handle to semaphore
1, // increase count by one
NULL) ) // not interested in previous count
{
printf("ReleaseSemaphore error: %d\n", GetLastError());
}
break;
// The semaphore was nonsignaled, so a time-out occurred.
case WAIT_TIMEOUT:
printf("Thread %d: wait timed out\n", GetCurrentThreadId());
break;
}
}
return TRUE;
}
With that, although what determines the filling of the semaphore is the thread, in a practical sense it is determined by the complete execution and closing of the handles of the process.
But this looks as a lame way to solve this problem and I bet doing it this way is likely to give problems in the future if extra things are needed from those processes.
How can I create a semaphore so what would really determine the filling of the semaphore would be the processes? To clarify, this would be one possible solution that I don't think it is possible anyhow.
Let's consider that you could Create a Process by something like this:
aThread[i] = CreateProcess(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&ThreadID); // receive thread identifier
Then LPTHREAD_START_ROUTINE would be equivalent in its working but for processes.
Semaphores are supposed to support Interprocess Synchronization in Windows API, but I cannot find any example that specifically uses processes, and I don't get the idea of how could it be done.
Any idea on how to achieve what I want?
Regards.
You want a named semaphore. Where each process shares the semaphore by creating it with the same name.
Create a named semaphore. Same as you have before, but that last parameter gets a string passed to it:
HANDLE hSemaphore = CreateSemaphore(NULL,
MAX_SEM_COUNT,
MAX_SEM_COUNT,
L"TheSemaphoreForMyApp");
Child processes, upon being started, can attach to that same semaphore and get a handle to it by using OpenSemaphore.
HANDLE hSemaphore = OpenSemaphore(EVENT_ALL_ACCESS,
FALSE,
L"TheSemaphoreForMyApp");
You don't have to hardcode a string as the semaphore name. The parent process can create a unique name each time, and then passes that name (e.g. command line parameter) to the child process. That will allow for multiple instances of your program with child processes to cooperate.
The function WaitForSingleObject returns timeout flag("WAIT_OBJECT_0") in all cases.
Only for testing I have commented this line
(while((WaitForSingleObject(ovread.hEvent,timeout)==WAIT_OBJECT_0)))
and the comport responds as expected.
I have tried various timeouts including INFINITE.
Can someone tell me where the error could be occurring.
int timeout=500;
OVERLAPPED ovread;
memset(&ovread, 0, sizeof(ovread));
ovread.hEvent = CreateEvent( 0,true,0,0);
while((WaitForSingleObject(ovread.hEvent,timeout)==WAIT_OBJECT_0))
{
//Execute the following code
ReadFile(h,buf,sizeof(buf),&read,&ovread);
}
The reading logic should more or less use the following code flow:
int timeout = 500;
OVERLAPPED ovread = {0}
ovread.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ovread.hEvent == NULL) {
// Error creating overlapped event; abort.
return FALSE;
}
if (!ReadFile(h, buf, sizeof(buf), &read, &ovread)) {
if (GetLastError() != ERROR_IO_PENDING) {
// Handle error in communications
}
else {
DWORD ret = WaitForSingleObject(ovread.hEvent,timeout);
switch (ret) {
case WAIT_OBJECT_0:
HandleASuccessfulRead(buf, read);
break;
case WAIT_TIMEOUT:
// Handle timeout
break;
case WAIT_FAILED:
// Handle failure
break;
default:
// what else to handle?
break;
}
}
}
else {
// read completed immediately
HandleASuccessfulRead(buf, read);
}
If I'm using WaitForMultipleObjects, and the function returns WAIT_TIMEOUT, how can I get which object or objects caused the timeout to occur?
Another question I have is if multiple objects are signaled, since the return value only returns the first object that it detects as signaled, how do I get the other objects which are signaled?
#include <windows.h>
#include <stdio.h>
HANDLE ghEvents[2];
DWORD WINAPI ThreadProc( LPVOID );
int main( void )
{
HANDLE hThread;
DWORD i, dwEvent, dwThreadID;
// Create two event objects
for (i = 0; i < 2; i++)
{
ghEvents[i] = CreateEvent(
NULL, // default security attributes
FALSE, // auto-reset event object
FALSE, // initial state is nonsignaled
NULL); // unnamed object
if (ghEvents[i] == NULL)
{
printf("CreateEvent error: %d\n", GetLastError() );
ExitProcess(0);
}
}
// Create a thread
hThread = CreateThread(
NULL, // default security attributes
0, // default stack size
(LPTHREAD_START_ROUTINE) ThreadProc,
NULL, // no thread function arguments
0, // default creation flags
&dwThreadID); // receive thread identifier
if( hThread == NULL )
{
printf("CreateThread error: %d\n", GetLastError());
return 1;
}
// Wait for the thread to signal one of the event objects
dwEvent = WaitForMultipleObjects(
2, // number of objects in array
ghEvents, // array of objects
FALSE, // wait for any object
5000); // five-second wait
// The return value indicates which event is signaled
switch (dwEvent)
{
// ghEvents[0] was signaled
case WAIT_OBJECT_0 + 0:
// TODO: Perform tasks required by this event
printf("First event was signaled.\n");
break;
// ghEvents[1] was signaled
case WAIT_OBJECT_0 + 1:
// TODO: Perform tasks required by this event
printf("Second event was signaled.\n");
break;
case WAIT_TIMEOUT:
// How can I get which object timed out?
printf("Wait timed out.\n");
break;
// Return value is invalid.
default:
printf("Wait error: %d\n", GetLastError());
ExitProcess(0);
}
// Close event handles
for (i = 0; i < 2; i++)
CloseHandle(ghEvents[i]);
return 0;
}
DWORD WINAPI ThreadProc( LPVOID lpParam )
{
// lpParam not used in this example
UNREFERENCED_PARAMETER( lpParam);
// Set one event to the signaled state
if ( !SetEvent(ghEvents[0]) )
{
printf("SetEvent failed (%d)\n", GetLastError());
return 1;
}
return 0;
}
When the WaitForMultipleObjects(...) returns with the WAIT_TIMEOUT return code, it indicates that none of your you objects you waited for signaled within the given amount of time.
The function essentially sleeps for the time you specify as timeout and only returns earlier, if one of the waitable objects gets signaled before that time. That means that the WAIT_TIMEOUT return code is not associated with any of the objects you wait for.
Your second question is partialy answered by Eregriths comment. To check if other objects are also signaled, you could call WaitForMultipleObjects(...) again, and depending on your needs, set the timeout value to 0 (do not wait). When WaitForMultipleObjects(...) returns with WAIT_TIMEOUT you know that no other objects were in a signaled state at the time of your call, but you should keep in mind, that the object, that caused your first call to return could potentially be signaled again. So you could either exclude it from your array or simply check a single object for its state with the WaitForSingleObject(...) function.
If you want to make sure all objects are signaled, you can also play with the bWaitAll parameter. WaitForMultipleObjects(...) will then only return if all your objects are in a signaled state.,
Hope that helps a bit.
ok...burned out on this one...scratching my head all day. I have a very simple, single purpose c++ DLL (StartApplication.dll) used to start an application.
Works fine in WinXP, but not in win7
Uses CreateProcess() with DEBUG_PROCESS (so i can wait for the program to finish before terminating).
If I monitor processes in Task Manager, I can see the process start, but no window is created and nothing further happens
If I change to NORMAL_PRIORITY_CLASS, the program will execute as it should (but i lose the ability to wait around before terminating as I can only do this while debugging)
Error code gives me STATUS_ACCESS_VIOLATION
I have UAC turned off and setting the executable to run as Administrator and with WinXP compatibility does nothing
Heres the code. Any thoughts would be greatly appreciated
//...blah blah...handful of stuff preceding this to set up command line and
//directories etc....not of use here probably...
SECURITY_ATTRIBUTES sa = {0}; sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.bInheritHandle = TRUE;
STARTUPINFO si = {0}; si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = (NULL == stdOutFileName)? INVALID_HANDLE_VALUE :
::CreateFile(stdOutFileName, GENERIC_WRITE, FILE_SHARE_READ, &sa
, CREATE_ALWAYS, 0, NULL);
si.hStdError = (NULL == stdErrFileName)? INVALID_HANDLE_VALUE :
::CreateFile(stdErrFileName, GENERIC_WRITE, FILE_SHARE_READ, &sa
, CREATE_ALWAYS, 0, NULL)
PROCESS_INFORMATION pi = {0};
if (::CreateProcess(useApplicationName? applicationName : NULL, processCommandLine
, NULL, NULL, TRUE, /*NORMAL_PRIORITY_CLASS*/DEBUG_PROCESS, NULL, currentDirectory, &si, &pi))
{
BOOL cont = TRUE;
while (cont)
{
DWORD continueStatus = DBG_CONTINUE;
DEBUG_EVENT debugEvent = {0};
if (!::WaitForDebugEvent(&debugEvent, INFINITE))
{
errorCode = ErrorCode_Other;
::TerminateProcess(pi.hProcess, 0);
break;
}
else
{
switch (debugEvent.dwDebugEventCode)
{
case EXCEPTION_DEBUG_EVENT:
switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_ACCESS_VIOLATION:
case EXCEPTION_DATATYPE_MISALIGNMENT:
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
case EXCEPTION_FLT_DENORMAL_OPERAND:
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
case EXCEPTION_FLT_INEXACT_RESULT:
case EXCEPTION_FLT_INVALID_OPERATION:
case EXCEPTION_FLT_OVERFLOW:
case EXCEPTION_FLT_STACK_CHECK:
case EXCEPTION_FLT_UNDERFLOW:
case EXCEPTION_INT_DIVIDE_BY_ZERO:
case EXCEPTION_INT_OVERFLOW:
case EXCEPTION_PRIV_INSTRUCTION:
case EXCEPTION_IN_PAGE_ERROR:
case EXCEPTION_ILLEGAL_INSTRUCTION:
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
case EXCEPTION_STACK_OVERFLOW:
case EXCEPTION_INVALID_DISPOSITION:
case EXCEPTION_INVALID_HANDLE:
errorCode = ErrorCode_ApplicationException;
*exceptionCode = debugEvent.u.Exception.
ExceptionRecord.ExceptionCode;
::TerminateProcess(pi.hProcess, 0);
break;
default:
;
}
break;
case EXIT_PROCESS_DEBUG_EVENT:
cont = FALSE;
break;
default:
;
}
::ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId
, continueStatus);
}
}
::GetExitCodeProcess(pi.hProcess, reinterpret_cast<LPDWORD>(exitCode));
::CloseHandle(pi.hProcess);
::CloseHandle(pi.hThread);
}
if (INVALID_HANDLE_VALUE != si.hStdOutput)
::CloseHandle(si.hStdOutput);
if (INVALID_HANDLE_VALUE != si.hStdError)
::CloseHandle(si.hStdError);
return errorCode;
}
Your code terminates the whole process after the first exception occures.
Normally you should let the program take care of exceptions, only if the exception wasn't handled the process will terminate.
To see if an exception was fatal (ie. not handled the first time around) check u.Exception.dwFirstChance:
If it's 0, set your error codes accordingly and terminate.
otherwise, the exception occured for the first time, you should call ContinueDebugEvent with DBG_EXCEPTION_NOT_HANDLED to pass the exception to the process.
EDIT
If you only want to watch exceptions and not handle them from inside the debugger, you should always continue with DBG_EXCEPTION_NOT_HANDLED.
There's one catch:
Right before the main thread starts, Windows raises an INT3 exception which needs to be passed to the process (DBG_CONTINUE).
Pseudo code:
bool FirstInt3 = true;
while (cont)
{
DWORD continueStatus = DBG_EXCEPTION_NOT_HANDLED;
// ....
switch(...)
{
case EXCEPTION_DEBUG_EVENT:
if(!FirstChance)
{
// Fatal exception
// Log Exception that terminated the program here
// Don't do anything else, Windows automatically terminates the process
// You will get an EXIT_PROCESS_DEBUG_EVENT on the next event
}
switch (debugEvent.u.Exception.ExceptionRecord.ExceptionCode)
{
case EXCEPTION_BREAKPOINT:
if(FirstInt3)
{
FirstInt3 = false;
continueStatus = DBG_CONTINUE;
break;
}
default:
// Log ExceptionCode here
break;
}
break;
}
If I've understand you correctly, you're using DEBUG_PROCESS just so that you can wait until the process exits. That's major overkill.
To wait until the process has exited, use WaitForSingleObject (or another wait function as appropriate) on pi.hProcess.
#pezcode is right - don't just end the process on receiving first exception from the debuggee, let it run normally. Debugger (your code) will anyway receive all exceptions occurring in the debuggee (first chance exceptions).
I would suggest you to first minimize the debugger-loop logic, and also try not to attach and handles to process. Keep it simple first, then move ahead.