C++ Builder 10.2: Thread blocks WaitForInputIdle - c++

I've got the following scenario: An Application B is supposed to start an application A and then to wait for A becoming idle. For this purpose, B uses CreateProcess in combination with WaitForInputIdle, and unfortunately the timeout of this command has been set to INFINITE.
This is the corresponding part of B's source code:
void StartA(void){
STARTUPINFO siInfo;
PROCESS_INFORMATION piInfo;
ZeroMemory(&siInfo, sizeof(siInfo));
ZeroMemory(&piInfo, sizeof(piInfo));
CreateProcess(L"A.exe", L"", 0, 0,
false, CREATE_DEFAULT_ERROR_MODE, 0, 0,
&siInfo, &piInfo);
WaitForInputIdle(piInfo.hProcess, INFINITE); // A will block this command!
CloseHandle(piInfo.hProcess);
CloseHandle(piInfo.hThread);
}
When I call my application A from this application B, B will be blocked by its WaitForInputIdle command forever due to the SendMessage command invoked by A's TestThread. If I create the TestThread only after the FormShow event, then WaitForInputIdle will return as expected. That's a solution and though I'm aware of the article WaitForInputIdle waits for any thread, which might not be the thread you care about, I like to understand what actually happens here.
This is the simplified source code of application A. It just consists out of a TForm and the class TestThread, which is derived from TThread.
class TestThread : public TThread {
public:
__fastcall TestThread(HWND in_msg) : msg(in_msg), TThread(false) {};
virtual __fastcall ~TestThread(){};
private:
void __fastcall Execute(){
// Next line leads to WaitForInputIdle blocking
SendMessage(msg, WM_USER, NULL, NULL);
while(!Terminated) Sleep(1);
}
HWND msg;
};
class TFormA : public TForm{
private:
TestThread * testthread_p;
public:
__fastcall TFormA(TComponent* Owner){
testthread_p = new TestThread(Handle);
}
virtual __fastcall ~TFormA(){}
};
Why does the command WaitForInputIdle fail to detect the idle state of application A?

The launched app never has a chance to enter an "input idle" state.
Assuming TFormA is the app's MainForm, it gets created at app startup, and thus creates the thread, before the VCL's main UI message loop starts running (when Application->Run() is called by WinMain()).
Even though the worker thread is using SendMessage() and not PostMessage(), it is sending messages across thread boundaries, so each message is not dispatched to the window until the receiving thread (in this case, the main UI thread) calls (Peek|Get)Message(). This is stated in the SendMessage() documentation:
Messages sent between threads are processed only when the receiving thread executes message retrieval code. The sending thread is blocked until the receiving thread processes the message.
By the time the main UI message loop starts running, one message from the thread has already been sent to the window and is waiting to be dispatched. Subsequent messages are being sent with a 1ms delay between them. So, the first time the main UI message loop attempts to retrieve a message from the queue, there is already a message waiting. By the time the loop dispatches that message for processing and goes back to the queue to wait for a message, there is already a new message waiting for it.
The WaitForInputIdle() documentation says:
The WaitForInputIdle function enables a thread to suspend its execution until the specified process has finished its initialization and is waiting for user input with no input pending. If the process has multiple threads, the WaitForInputIdle function returns as soon as any thread becomes idle.
The main UI thread has continuous messages pending from the thread, so it can't become "input idle". And the worker thread does not retrieve inbound messages of its own, so it can't become "input idle", either (see WaitForInputIdle waits for any thread, which might not be the thread you care about).
Thus, the app process as a whole never becomes "input idle", so WaitForInputIdle() blocks until its timeout elapses, which in this case is INFINITE, so it blocks indefinately.
The Form's OnShow event is not fired until well after the main UI message loop is running and has already processed several other window messages, so the app has time to go "input idle", unblocking WaitForInputIdle(), before the thread gets created and starts sending messages to the window.

Related

Which thread calls the windows proc callback function?

I am a bit unsure which thread calls the wndproc callback function. Is it the main thread from the application, like in the message loop or is a seperate windows thread ? The function has access to class objects and I dont want there to be any corruption of data if 2 thread happend to access the class object at the same time.
Yes, it is main thread of application.
An application's main thread starts its message loop after
initializing the application and creating at least one window. After
it is started, the message loop continues to retrieve messages from
the thread's message queue and to dispatch them to the appropriate
windows. The message loop ends when the GetMessage function removes
the WM_QUIT message from the message queue.
Source: About Messages and Message Queues

threads sync with events

Newbie to embedded systems here. I have to synchronize two threads with events. My code show only "Show in edit box 2sec" and is not going to secondthread to show what I have there. I should show in an edit box for 2 seconds with one thread a message and after two seconds i should show for 3 seconds another message. This should be repeat forever.
void FirstThread(void)
{
int i;
//write data to edit box
CString szEdit;
szEdit.Format(_T("Show in edit box 2sec"));
m_editbox->SetWindowText(szEdit);
while(1){
WaitForSingleObject (hEvent, INFINITE);
for(i=0;i<1;i++){
Sleep(2000);
}
SetEvent (hEvent);
}
}
void SecondThread (void)
{
int i;
//write data to edit box
CString szEdit;
szEdit.Format(_T("Show in edit box 3 sec"));
m_editbox->SetWindowText(szEdit);
while(1){
WaitForSingleObject (hEvent, INFINITE);
for(i=0;i<1;i++){
Sleep(3000);
}
SetEvent (hEvent);
}
}
You should use two different events, one signaling the end of sleeping in the first thread, the other one - in the second thread. (Initially, one of these events should be set (signaled), the other - unset.)
There are problems with your approach. MFC will not permit you to access a control from a thread that did not create it, and placing WaitForSingleObject or Sleep within the main thread stops it from processing messages so the program becomes "unresponsive".
You could do this with no threads, no WaitForSingleObject, no Sleep and no events by using a timer in the main thread. The main thread would initially call SetTimer, then process the WM_TIMER message to change the control text periodically. Meanwhile, the program would be able to process any other messages normally, between the WM_TIMER messages.

How do I SendMessage() to a window created on another thread?

I have a situation where I want to SendMessage to a window that was created on another thread than the one that is calling SendMessage.
The default behaviour seems to be block forever and not work.
So I changed the call to PostMessage, which didn't block the sending thread, but the message never appears to arrive at the intended window.
So how do I SendMessage to a window created on a separate thread, or is this impossible?
The PostThreadMessage function posts a message to the message queue of the specified thread. you can specified Identifier of the thread to which the message is to be posted. is that you want?
What is the thread that owns the target window doing? It needs to be pumping messages in order to be able to receive messages that are either sent or posted to it. Typically this is done by having a GetMessage/TranslateMessage/DispatchMessage loop. If the thread is doing something else - such as blocking waiting for an event or mutex or IO to complete, or is busy in some other loop carrying out a calculation, it won't receive messages: SendMessage to the thread will block, and PostMessage will post but not get delivered.
If that target thread needs to both manage events or similar, and it also owns a window, you may need to use MsgWaitForMultipleObjects in that thread's message loop.
You are running into a deadlock. An example, if you SendMessage to another thread, then the windowProc in that thread does SendMessage back to your window, they will lock waiting each other forever.
You need to either fix PostMessage (it does deliver messages, there's just error in your code somewhere), or be very careful about who calls who and when.
To protect against threads that are busy or hung, there is SendMessageTimeout.
Each control you create belongs to the thread that created it, which means that the WndProc for that control will be running in the thread that created the control. You send messages with SendMessage and PostMessage freely to any control.
The issue with CWnd::PostMessage and CWnd::SendMessage is the same. The message is being pushed out, and not being received by anything. SendMessage is blocking by design; it's job is to block the thread until the message is received.
MSDN says this about SendMessage:
"The SendMessage function calls the window procedure for the specified
window and does not return until the window procedure has processed
the message."
It is possible to send a message to window on another thread using CWnd::PostThreadMessage or winapi PostMessage. When you create the window you can use GetSafeHwnd() to get the handle or you can use a thread ID when the thread is created.

Wait until window closes when message loop is on another thread

In one C++ application I have a window whose message loop runs in a separate thread because the main thread is busy calculating and rendering a simulation. The window acts as a log window for the simulation. When the simulation throws an exception, the simulation closes and the log window displays the details.
Now the main thread should wait until the log window is closed. Since the message loop runs on a separate thread, I tried to
WaitForSingleObject(logwindow->thread, INFINITE);
from the main thread.
However, this seems to block the message pump and the log window freezes. So how do I correctly wait until a window is closed or a thread ends?
ED: The window is created on the main thread but runs on a different thread. I'll go ahead and change it so it creates on the message loop thread too.
You have a few options.
Run all the UI out of the main thread and get the worker thread to synchronize reporting back to the main thread to display, for example via PostMessage or SendMessage.
Don't wait at all and get the worker thread to post a message to the main thread when the worker is done.
Use MsgWaitForMultipleObjects for your wait.
To elaborate on MsgWaitForMultipleObjects, it's a wait function that can be configured to return when messages arrive in the queue. Thus you can keep your message pump alive whilst also using a blocking wait in between processing queued messages.
In pseudo-code you would write it like this:
do
{
WaitResult = MsgWaitForMultipleObjects(1, hThread, TRUE, INFINITE, QS_ALLEVENTS);
if (WaitResult == MessageArrivedOnQueue)
PumpMessageQueue();
} while (WaitResult != WaitHandlesSignaled)
The fact that the log window is freezing while the main thread is in a blocking wait suggests the worker thread is sending a message to the main thread and then waiting for a reply, but the main thread is already blocked and cannot reply to it. That is a classic deadlock situation for both threads. You should use MsgWaitForMultipleObjects() instead of WaitForSingleObject() in the main thread to detect when new messages need processing while waiting, eg:
do
{
DWORD dwRet = MsgWaitForMultipleObjects(1, &(logwindow->thread), FALSE, INFINITE, QS_ALLINPUT);
if (dwRet == 0xFFFFFFFF) break;
if (dwRet == (WAIT_OBJECT_0 + 1))
{
process messages here...
}
}
while (dwRet != WAIT_OBJECT_0);
I agree with David that you really should be doing all UI work in the main thread and do your calculations in the worker thread, not the other way around.

How to guarantee signal delivery from multiple children

As part of a Linux benchmark application, I have a parent process that forks multiple children that will each perform a task in parallel. I'm using signals to coordinate between them since I'm looking for as accurate of timing as possible. Each child will prepare for the test, then enter a 'barrier' controlled by the parent via signals.
Once all the children have entered the barrier, the parent records the time stamp, and signals the child processes to begin. As soon as the child finishes each portion of the test they signal the parent before entering the next barrier. The parent is listening for these signals and once it receives them from all of the child processes, it records the completion time(s).
My problem is that the program terminates non-deterministically; the signals don't always get delivered. The signal handler could not be any simpler:
void sig_child_ready (int sig)
{
num_child_ready++;
}
num_child_ready is declared as volatile sig_atomic_t. I've tried using sigprocmask without success in a loop like this:
sigprocmask (SIG_BLOCK, &mask, &oldmask);
while (num_child_ready < num_child)
{
/* waiting for child signals here */
sigsuspend (&oldmask);
}
sigprocmask (SIG_UNBLOCK, &mask, NULL);
I'm not sure how to proceed from here. Am I correct that sigprocmask is needed to 'queue' the signals so they are processed one by one?
Or, consider this hypothetical scenario: the parent receives a signal, is executing its handler, then receives ANOTHER identical signal. Is the signal handler called recursively? ie will it execute the second handler before returning to, and completing the first handler?
I'm just looking to make sure all of the signals are delivered as synchronously as possible.
Normal signals are not queued, and that's likely the cause of your problem.
If one signal arrives before the handler has been run for a past signal, they'll get merged and there's little you can do about that - you're probably better off using some other form of IPC to do this kind of synchronization.
You could use "realtime signals", which do get queued. You'd send signals with sigqueue() and
"receive" them with sigwaitinfo() or establishing a signal handler setting the SA_SIGINFO flag in a struct sigaction