Problem with ReleaseMutex - c++

I'm writing an API and I'm facing problems with a Mutex.
The main thread, at some point, does:
void sendMessage (char* g_lpTxBuffer)
{
for ( int i = 0; ( i < 2) && ( FALSE == g_bAckRecvd) ; i++ )
{
sendToSerial( g_lpTxBuffer );
g_iRecvMessage = YES;
g_iState = WAITING_FOR_ACK;
Sleep(50);
}
WaitForSingleObject(g_hMutex, INFINITE);
and I have a child thread, who does:
DWORD WINAPI ThreadProc(void* lpv)
{
g_hMutex = OpenMutex( MUTEX_ALL_ACCESS, FALSE, "MUTEX_RECEIVE" );
while (TRUE)
{
g_bNAKflag = FALSE;
if ( YES == g_iRecvMessage )
{
WaitForSingleObject(g_hMutex, INFINITE);
receiveMessage();
}
if ( MESSAGE_READY == g_iState )
{
processMessage(); // interpret the message
if ( FALSE == g_bNAKflag )
{
g_iState = IDLE;
}
ReleaseMutex(g_hMutex);
}
} // while
return 0;
}
What I found is, if I place the ReleaseMutex() at the place pointed above, the main thread never comes back from the WaitForSingleObject() function. However, if I place it inside the
if ( YES == g_iRecvMessage )>
(which is not good because the receiveMessage is called several times, to receive byte per byte from the serial) it works, and the WaitForSingleObject runs fine..
I create the mutex with
g_hMutex = CreateMutex(NULL, FALSE, "MUTEX_RECEIVE");
and I checked, the ReleaseMutex() returns true
Any ideas?
Thanks..

Related

WaitForSingleObject and WaitForMultipleObjects equivalent in modern c++?

The windows functions, CreateEvent, WaitForSingleObject and WaitForMultipleObjects are handy but only used in win32. Can I replace them using Modern C++ threading in a generic way?
I find a post, https://vorbrodt.blog/2019/02/08/event-objects/, to manually set and reset event in modern c++. is there a better way to do that?
The below is the code snippet of old windows code:
DWORD TX_LAYER::__TX_THREAD(HANDLE *done)
{
CONNECTIONS *con = nullptr;
void *temp = nullptr;
const HANDLE h[] =
{
*doneEvent,
evtTX
};
const DWORD num_evts = _countof(h);
while ( true )
{
DWORD ret = -1;
ret = WaitForMultipleObjects(num_evts, h, FALSE, INFINITE);
// Stop signal or critical error.
if ( (ret == 0) || (ret == WAIT_FAILED) )
break;
// TX the packet.
EnterCriticalSection(&csTX);
if ( _tx.empty() == true )
{
ResetEvent(evtTX);
LeaveCriticalSection(&csTX);
continue;
}
temp = *_tx.begin();
_tx.erase(_tx.begin());
if ( _tx.empty() == true )
ResetEvent(evtTX);
else
SetEvent(evtTX);
LeaveCriticalSection(&csTX);
....
....
....
temp = nullptr;
}

Synchronize threads in C++

I have three threads - Thread1 prints "Good", Thread2 prints "Morning" and Thread3 prints "All". How do I use these threads to keep printing “Good Morning All” on the screen continuously?
For one, you are simply wasting resources.
However, assuming that you really need this to accomplish something more important than just printing words, here is a suggestion:
create 3 mutexes (pthread_mutex)
pthread_mutex_t m_Good, m_Morning, m_all;
pthread_mutex_init(&m_Good, NULL);
pthread_mutex_init(&m_Morning, NULL);
pthread_mutex_init(&m_All, NULL);
Lock last two mutexes
pthread_mutex_lock(&m_Morning);
pthread_mutex_lock(&m_All);
In first thread prints its message then unlock second mutex.
while(true){
if(pthread_mutex_lock(&m_Good)==0){
printf("GOOD ");
pthread_mutex_unlock(&m_Morning);
pthread_mutex_lock(&m_Good);
}
}
second thread prints message, locks its mutex and unlock third
third thread prints its message, unlock first mutex and locks third mutex
Here's a simple lock-free implementation for forcing sequential execution of threads. It uses an atomic state variable that can represent four possible states:
working = one of the threads is working
ready_for_task1 = it is task1's turn to start working
ready_for_task2 = it is task2's turn to start working
ready_for_task3 = it is task3's turn to start working
The general idea is to cycle through these states:
ready_for_task1 ->
working ->
ready_for_task2 ->
working ->
ready_for_task3 ->
working ->
ready_for_task1 ->
...
First part, define the states, declare the global atomic state, and define a guard class that performs the state transitions. The guard constructor of the guard will "busy" wait by atomically checking for its ready state and switching the state to working. The guard destructor will set the state to the next task's ready state.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <atomic>
enum State { ready_for_task1, ready_for_task2, ready_for_task3, working };
static std::atomic< State > state_;
class TransitionGuard {
public:
TransitionGuard(State start, State finish) : finish_(finish) {
State expecting = start;
while( !state_.compare_exchange_weak( expecting, working ) ) {
expecting = start;
asm("pause");
}
}
~TransitionGuard() {
state_.store( finish_ );
}
private:
const State finish_;
};
Then each thread runs their own loop, printing their word under their respective transition guard.
void * task1( void * data )
{
while( true ) {
TransitionGuard guard( ready_for_task1, ready_for_task2 );
printf( "Good" );
}
}
void * task2( void * data)
{
while( true ) {
TransitionGuard guard( ready_for_task2, ready_for_task3 );
printf( " Morning" );
}
return NULL;
}
void * task3( void * data)
{
while( true ) {
TransitionGuard guard( ready_for_task3, ready_for_task1 );
printf( " All\n" );
}
return NULL;
}
And finally, you'll want to initialize the state before creating the threads.
int main( int argc, const char ** argv )
{
state_ = ready_for_task1;
pthread_t thread1, thread2, thread3;
if( pthread_create( &thread1, NULL, task1, NULL ) )
{
fprintf( stderr, "thread1 failed to start\n" );
exit(EXIT_FAILURE);
}
if( pthread_create( &thread2, NULL, task2, NULL ) )
{
fprintf( stderr, "thread2 failed to start\n" );
exit(EXIT_FAILURE);
}
if( pthread_create( &thread3, NULL, task3, NULL ) )
{
fprintf( stderr, "thread3 failed to start\n" );
exit(EXIT_FAILURE);
}
pthread_join( thread1, NULL );
pthread_join( thread2, NULL );
pthread_join( thread3, NULL );
fprintf( stderr, "threads joined. exiting.\n" );
exit(EXIT_SUCCESS);
}

Can't get print job notification with status JOB_STATUS_DELETED

I want to get notification when print job has been completed or deleted. Now I see that notification mechanism provides the JOB_STATUS_DELETING, but no JOB_STATUS_DELETED status can be got.
I found something similar Here, but it doesn't solve my problem.
I'm doing next thing:
HANDLE hChange = FindFirstPrinterChangeNotification(hPrinter,
PRINTER_CHANGE_ALL,
0,
&NotificationOptions);
DWORD dwChange;
HANDLE aHandles[2];
aHandles[0] = hChange;
aHandles[1] = owner->GetStopRequestEvent();
while (hChange != INVALID_HANDLE_VALUE)
{
// sleep until a printer change notification wakes this thread or the
// event becomes set indicating it's time for the thread to end.
WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);
if (WaitForSingleObject(hChange, 0U) == WAIT_OBJECT_0)
{
FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);
if (pNotification != NULL)
{
// if a notification overflow occurred,
if (pNotification->Flags & PRINTER_NOTIFY_INFO_DISCARDED)
{
DWORD dwOldFlags = NotificationOptions.Flags;
// we must refresh to continue
NotificationOptions.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
FreePrinterNotifyInfo(pNotification);
FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);
NotificationOptions.Flags = dwOldFlags;
}
// iterate through each notification
for (DWORD x = 0; x < pNotification->Count; x++)
{
PRINTER_NOTIFY_INFO_DATA data = pNotification->aData[x];
if (data.Type == JOB_NOTIFY_TYPE)
{
if (data.Field == JOB_NOTIFY_FIELD_STATUS)
{
if (data.NotifyData.adwData[0] & ( JOB_STATUS_DELETED | JOB_STATUS_DELETING | JOB_STATUS_PRINTED))
{
owner->SendJobsData(data.NotifyData.adwData[0]);
}
......
when i delete job, JOB_NOTIFY_FIELD_STATUS passes only DELETING, and no any further status-notification, but I really need to get DELETED status. What am I doing wrong?
full code of poller method here:
void Poll(JobTracker* owner, CServiceBase* service)
{
HANDLE hPrinter = NULL;
HANDLE hNotification;
if (!OpenPrinter(owner -> GetPrinterName(), &hPrinter, NULL))
return;
PPRINTER_NOTIFY_INFO pNotification = NULL;
WORD JobFields[] =
{
JOB_NOTIFY_FIELD_PRINTER_NAME,
JOB_NOTIFY_FIELD_MACHINE_NAME,
JOB_NOTIFY_FIELD_PORT_NAME,
JOB_NOTIFY_FIELD_USER_NAME,
JOB_NOTIFY_FIELD_NOTIFY_NAME,
JOB_NOTIFY_FIELD_DATATYPE,
JOB_NOTIFY_FIELD_PRINT_PROCESSOR,
JOB_NOTIFY_FIELD_PARAMETERS,
JOB_NOTIFY_FIELD_DRIVER_NAME,
JOB_NOTIFY_FIELD_DEVMODE,
JOB_NOTIFY_FIELD_STATUS,
JOB_NOTIFY_FIELD_STATUS_STRING,
JOB_NOTIFY_FIELD_DOCUMENT,
JOB_NOTIFY_FIELD_PRIORITY,
JOB_NOTIFY_FIELD_POSITION,
JOB_NOTIFY_FIELD_SUBMITTED,
JOB_NOTIFY_FIELD_START_TIME,
JOB_NOTIFY_FIELD_UNTIL_TIME,
JOB_NOTIFY_FIELD_TIME,
JOB_NOTIFY_FIELD_TOTAL_PAGES,
JOB_NOTIFY_FIELD_PAGES_PRINTED,
JOB_NOTIFY_FIELD_TOTAL_BYTES,
JOB_NOTIFY_FIELD_BYTES_PRINTED
};
PRINTER_NOTIFY_OPTIONS_TYPE Notifications[1] =
{
{
JOB_NOTIFY_TYPE,
0,
0,
0,
sizeof(JobFields) / sizeof(JobFields[0]),
JobFields
},
};
PRINTER_NOTIFY_OPTIONS NotificationOptions =
{
2,
PRINTER_NOTIFY_OPTIONS_REFRESH,
sizeof(Notifications) / sizeof(Notifications[0]),
Notifications
};
// get a handle to a printer change notification object.
HANDLE hChange = FindFirstPrinterChangeNotification(hPrinter,
PRINTER_CHANGE_ALL,
0,
&NotificationOptions);
DWORD dwChange;
HANDLE aHandles[2];
aHandles[0] = hChange;
aHandles[1] = owner->GetStopRequestEvent();
while (hChange != INVALID_HANDLE_VALUE)
{
// sleep until a printer change notification wakes this thread or the
// event becomes set indicating it's time for the thread to end.
WaitForMultipleObjects(2, aHandles, FALSE, INFINITE);
if (WaitForSingleObject(hChange, 0U) == WAIT_OBJECT_0)
{
FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);
if (pNotification != NULL)
{
// if a notification overflow occurred,
if (pNotification->Flags & PRINTER_NOTIFY_INFO_DISCARDED)
{
DWORD dwOldFlags = NotificationOptions.Flags;
// we must refresh to continue
NotificationOptions.Flags = PRINTER_NOTIFY_OPTIONS_REFRESH;
FreePrinterNotifyInfo(pNotification);
FindNextPrinterChangeNotification(hChange, &dwChange, &NotificationOptions, (LPVOID *) &pNotification);
NotificationOptions.Flags = dwOldFlags;
}
// iterate through each notification
for (DWORD x = 0; x < pNotification->Count; x++)
{
PRINTER_NOTIFY_INFO_DATA data = pNotification->aData[x];
if (data.Type == JOB_NOTIFY_TYPE)
{
if (data.Field == JOB_NOTIFY_FIELD_STATUS)
{
if (data.NotifyData.adwData[0] & ( JOB_STATUS_DELETED | JOB_STATUS_DELETING | JOB_STATUS_PRINTED))
{
owner->SendJobsData(data.NotifyData.adwData[0]);
}
}
if (data.Field == JOB_NOTIFY_FIELD_STATUS_STRING)
{
int a = 0;
}
}
else if (data.Type == PRINTER_NOTIFY_TYPE)
{
if (data.Field == PRINTER_NOTIFY_FIELD_STATUS)
{
int a = 0;
}
if (data.Field == PRINTER_NOTIFY_FIELD_STATUS_STRING)
{
int a = 0;
}
}
}
}
FreePrinterNotifyInfo(pNotification);
pNotification = NULL;
}
else if (WaitForSingleObject(owner->GetStopRequestEvent(), 0U) == WAIT_OBJECT_0)
{
FindClosePrinterChangeNotification(hChange);
hChange = INVALID_HANDLE_VALUE;
}
}
}
If anyone will face such task I will leave my way which I solve it.
I've noticed that every time when job leaves queue, the PRINTER_CHANGE_JOB_DELETE notification (i mean change of FindNextPrinterChangeNotification).
So, I just track task list in thread-owner class (JobTracker), and refresh it every time on any PRINTER_CHANGE_JOB. But before refresh it, I look at the difference and if I see that some job dissapeared (compare by JobId), I take my vector of jobs, and send to server missing job.

Using DebugActiveProcess and WaitForDebugEvent seems to hang

I have used DebugActiveProcess to attach a process. After that I used WaitForDebugEvent, but it seems that the application is stuck in some infinite loop and I am not able to debug the attached process.
Below is my code:
DebugActiveProcess( processID );
int temp = 0;
DEBUG_EVENT DBEvent;
while (1)
{
WaitForDebugEvent( &DBEvent, INFINITE );
if ( DBEvent.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT )
break;
if ( DBEvent.dwDebugEventCode == CREATE_PROCESS_DEBUG_EVENT )
{
//MessageBox(0,"Debugging started!","Ble",0);
temp = 1;
}
else if ( DBEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT )
{
if ( DBEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT )
{
ContinueDebugEvent( processID, qalsrvid, DBG_CONTINUE );
continue;
}
ContinueDebugEvent( processID, qalsrvid, DBG_EXCEPTION_NOT_HANDLED );
}
}
You are not calling ContinuteDebugEvent on CREATE_PROCESS_DEBUG_EVENT event.
If you have not read it yet, you should:
Writing Windows Debugger and Part 2

COM + WaitForSingleObject

I've been trying to find a good architecture for one application for the last few days, and after some research I'm finally stuck, and the reason is COM.
The app in question will have multiple GUI threads, and they will schedule work items for worker thread. The worker thread will initialize COM via CoInitialize(NULL);, create few COM components and will go into a loop which will wait for WaitForMultipleObjects(2, ...) (ExitEvent - to indicate that app is shutting down and ManualResetEvent - to indicate that there are actually work items to process), and on successful wait, will process the items and PostMessage them back to GUI threads. The ManualResetEvent will be reset inside worker if the queue will be empty and will happen inside queue critical section.
The problem is that COM, as usual, makes EVERYTHING 1000x harder...
If I understand correctly, CoInitialize(NULL); creates a hidden window, and any message posted during WaitForSingle/MultipleObject/s can cause a deadlock.
So, I need to call the MsgWaitForMultiple objects. Which in turn can fail if messages are not pumped correctly. Unfortunately, I can't quite understand how to pump them in a correct way. Do I have to create my own message loop? Will the app crash if COM decides to create a messagebox?
So far it seems I have to proceed like this?
HANDLE hEvents[2] = {};
int ThreadProc(LPVOID lpParam) {
int nRetVal = 0;
CoInitialize(NULL);
CComPtr<ISomething> smthn;
smthn.CoCreateInstance(...);
MSG msg = {};
bool bRun = true;
while(bRun) {
while(PeekMessage(&msg, ??NULL/-1??, 0, 0, PM_REMOVE)) { /*Which one here?*/
if(msg.Message == WM_QUIT) {
bRun = false;
nRetVal = msg.wParam;
break;
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(MsgWaitForMultipleObjects(2, &hEvents, ...)) {
if(exitevent) { bRun = false; nRetVal = 0; }
else if(processevent) { [processdata] }
}
}
smthn.release();
CoUninitialize();
return nRetVal;
}
But what about hidden window, messageboxes, am I even on the right path?
Just use CoWaitForMultipleHandles and it will do the necessary message pumping on the hidden COM window for inter-thread syncing.
The hidden window is of class OleMainThreadWndClass with OleMainThreadWndName as caption but on win9x its class is WIN95 RPC Wmsg. It's hidden which means you can't use straight EnumThreadWindows to find it.
Seems like overkill, but this worked for me :
int waitAndDispatch( HANDLE* event_handle, unsigned int ev_count, DWORD timeout )
{
int rval = -1;
bool bLoop = true; // if the loop should terminate
HANDLE* pHList = new HANDLE[ev_count];
for( unsigned int i = 0; i < ev_count; ++i )
{
pHList[i] = event_handle[i];
}
while( bLoop )
{
DWORD res = ::MsgWaitForMultipleObjects( ev_count, pHList, false, timeout, QS_ALLPOSTMESSAGE | QS_SENDMESSAGE );
if( res == WAIT_OBJECT_0 + ev_count ) // messages arrived
{
MSG tmpMsg;
bool hasMsg = true;
while( bLoop && hasMsg )
{
::PeekMessage( &tmpMsg, 0, 0, 0, PM_NOREMOVE );
if( ::PeekMessage( &tmpMsg, 0, WM_USER, WM_USER, PM_REMOVE ) || // WM_USER for COM
::PeekMessage( &tmpMsg, 0, 0, WM_KEYFIRST - 1, PM_REMOVE ) // all destroy update, ...
)
{
DWORD val = ::WaitForMultipleObjects( ev_count, pHList, false, 0 );
if( val >= WAIT_OBJECT_0 && val <= (WAIT_OBJECT_0 + ev_count) )
{
rval = val - WAIT_OBJECT_0;
bLoop = false;
}
::DispatchMessage( &tmpMsg );
}
else
{
hasMsg = false;
}
}
}
else if( res >= WAIT_OBJECT_0 && res < (WAIT_OBJECT_0 + ev_count) )
{
rval = res - WAIT_OBJECT_0;
bLoop = false;
}
else if( res == WAIT_TIMEOUT )
{
rval = ev_count;
bLoop = false;
}
else
{
rval = -1;
bLoop = false;
}
}
delete[] pHList;
return rval;
}
I had to write this piece for VB6 and its thread interactions over com compartments ... .
If you initialize your thread apartment with CoInitializeEx( 0, COINIT_MULTITHREADED ), your COM calls will not be queued into an message queue. But then you have the problem of objects created in different COM apartments. These need to be marshaled ... .