Internal message loop - c++

In my main dialog I have a function that creates a process and waits for it to finish. It might take up to 15-20 seconds. If I simply wait using WaitForSingleObject my dialog becomes unresponsive.
I want to use a combination of EnableWindow(FALSE), and an internal message loop to make my dialog block, but without looking like the app freezes, the way MessageBox and DoModal do. But I'm not sure how to do that an internal message loop.

I'm afraid your approach won't work. Your app is single-threaded, or at least your UI is. After you call WaitForSingleObject your thread is put to sleep and it won't process windows messages. The fact that you have an internal message loop won't matter. You should probably start a new thread and use it to wait for the process to finish, then notify your UI thread and exit. Or something along those lines.

Running internal message loop is rather trivial coding.
Something like below is all:
EnableWindow(FALSE);
while ( /* check for my exit condition */ )
{
MSG msg;
if(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if( !AfxGetApp()->PumpMessage() )
{
::PostQuitMessage(0);
}
}
}
EnableWindow(TRUE);
To wait for the process exit, you could use very short(<30ms) timeout WaitForSingleObject call in the message loop. Or MsgWaitForMultipleObjects. Or GetExitCodeProcess.
I'd like to recommend another approach.
1) Show new modal popup
2) Start the process in OnInitDialog handler and start a timer
3) Check if the process is still running in OnTimer handler, by GetExitCodeProcess
4) Call EndDialog when the process is no longer running

Try MsgWaitForMultipleObjects function; it can process Windows messages while waiting for the event object.

You could:
(a bit complicated) use MsgWaitForMultipleObjects (or MsgWaitForMultipleObjectsEx) to wait for the process to finish or for a message to arrive (processing it in the normal way).
(simple) use RegisterWaitForSingleObject to register a callback that is called in a separate thread when the process exits (and perhaps have that callback just post a message to your window).
(fairly simple) create your own thread to do the waiting in.
I'd go with the 2nd option.

DWORD ec;
if(CreateProcess( NULL, // No module name (use command line).
szExe, // Command line.
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
procFlags, // No creation flags.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi ) // Pointer to PROCESS_INFORMATION structure.
)
{
while(GetExitCodeProcess(pi.hProcess, &ec) && ec == STILL_ACTIVE)
{
MSG msg;
while(::PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if(!AfxGetApp()->PumpMessage())
{
::PostQuitMessage(0);
break;
}
}
// let MFC do its idle processing
LONG lIdle = 0;
while(AfxGetApp()->OnIdle(lIdle++))
;
}
}
if(ec)
{
CloseHandle(pi.hProcess);
}

Related

how to get process status ( running , killed ) event?

How to I get the status of another process?
i want to know the execution status of another process.
i want to receive and process the event as a inotify.
no search /proc by periods.
how to another process status (running , killed ) event?
SYSTEM : linux, solaris, aix
Linux
Under Linux (and probably many Unixes system) you can achieve this by using the ptrace call, then using waitpid to wait for status:
manpages:
ptrace call: http://man7.org/linux/man-pages/man2/ptrace.2.html
waitpid call: https://linux.die.net/man/2/waitpid
From the manpage:
Death under ptrace
When a (possibly multithreaded) process receives a killing signal
(one whose disposition is set to SIG_DFL and whose default action is
to kill the process), all threads exit. Tracees report their death
to their tracer(s). Notification of this event is delivered via
waitpid(2).
beware that you will need to have special authorization in certain cases. Take a look at /proc/sys/kernel/yama/ptrace_scope. (if you can modify the target program, you can also change the behavior of ptrace by calling ptrace(PTRACE_TRACEME, 0, nullptr, nullptr);
To use ptrace, first you must get your process PID, then call PTRACE_ATTACH:
// error checking removed for the sake of clarity
#include <sys/ptrace.h>
pid_t child_pid;
// ... Get your child_pid somehow ...
// 1. attach to your process:
long err;
err = ptrace(PTRACE_ATTACH, child_pid, nullptr, nullptr);
// 2. wait for your process to stop:
int process_status;
err = waitpid(child_pid, &process_status, 0);
// 3. restart the process (continue)
ptrace(PTRACE_CONT, child_pid, nullptr, nullptr);
// 4. wait for any change in status:
err = waitpid(child_pid, &process_status, 0);
// while waiting, the process is running...
// by default waitpid will wait for process to terminate, but you can
// change this with WNOHANG in the options.
if (WIFEXITED(status)) {
// exitted
}
if (WIFSIGNALED(status)) {
// process got a signal
// WTERMSIG(status) will get you the signal that was sent.
}
AIX:
The solution will need some adaptation to work with AIX, have a look at the doc there:
ptrace documentation: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.basetrf1/ptrace.htm
waitpid documentation: https://www.ibm.com/support/knowledgecenter/en/ssw_aix_72/com.ibm.aix.basetrf1/ptrace.htm
Solaris
As mentionned here ptrace may not be available on your version of Solaris, you may have to resort to procfs there.

Invalid handle error in TerminateThread

I have an application, which has registered handle routine via SetConsoleCtrlHandler . Thing is on break signal I have to do some cleanup before exiting, and that is when problems begin. Because, other threads keeps on running and using some of the resources which should freed I got access violation during cleanup. I tried to save thread instances which are using these resources and stop them before calling cleanup routine, but this did not help. I constantly get ERROR_INVALID_HANDLE. I tried to get thread instance via DuplicateHandle also I tried to save only thread id and then get thread handle via OpenThread function. But still invalid handle error is displayed.
Also, when I enumerate all thread instance and trying to terminate them I get the same error. It seems to me like there are some "magic" around handle routine, which does not allow to terminate other threads from it.
Listing for enumerating all threads
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (h != INVALID_HANDLE_VALUE) {
THREADENTRY32 te;
te.dwSize = sizeof(te);
if (Thread32First(h, &te)) {
do {
if (te.dwSize >= FIELD_OFFSET(THREADENTRY32, th32OwnerProcessID) +
sizeof(te.th32OwnerProcessID)) {
HANDLE thread = OpenThread(THREAD_TERMINATE, FALSE, te.th32ThreadID);
if (TerminateThread(thread , NUM_SIG_ACTION_1) == 0)
{
// printf("terminate failed (%d)\n", GetLastError());
if( SuspendThread(thread ) == -1)
{
// printf("suspend failed (%d)\n", GetLastError());
}
}
}
te.dwSize = sizeof(te);
} while (Thread32Next(h, &te));
}
CloseHandle(h);
}
Listing for get thread via DuplicateHandle
//code in working thread
DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &g_hWorkerThread ,
DUPLICATE_SAME_ACCESS, FALSE, DUPLICATE_SAME_ACCESS);
//code in handler routine
if (TerminateThread( g_hWorkerThread , NUM_SIG_ACTION_1 ) == 0)
{
printf("Terminate thread failed (%d)\n", GetLastError());
}
Listing for OpenThread
//code from worker thread
g_iWorkerThreadId = GetThreadId(GetCurrentThread());
//code in routine handler
HANDLE handle = OpenThread(THREAD_TERMINATE, FALSE, g_iWorkerThreadId);
if (TerminateThread( handle , NUM_SIG_ACTION_1 ) == 0)
{
printf("Terminate thread failed (%d)\n", GetLastError());
}
Is there anyway to force handle routine run in to current worker thread?
Any help will be appreciated.
Thanks on advance.
You're trying to do something yourself that the OS already does. Don't fight the system.
Let me suggest another way of working, that could simplify your code considerably.
When your main application thread gets the Ctrl signal, it wants to shut down the application.
You can have Windows do that for you, but you might leave resources in an undefined state, so that's why you want to shut down gracefully.
Likely, each thread already runs an event loop - that's the basic Windows applications paradigm. Upon the ctrl-signal, post events to your other threads and catch them in each thread's event loop. Add custom event code that will make them gracefully end themselves. You now only have to wait for all the thread handles to ensure all threads have ended.
Using TerminateThread is not a good idea, it is exactly the opposite of the graceful end of a thread.
How one can sure calling TerminateThread will free the resource that is in use?
Only killing a process guarantees freeing of kernel resources used by the process.
In my humble experiences, I didn't found any multi-thread program runs good and stably without the clear and explicit exit mechanism.
Each thread must have an exit condition, when exiting it must free the resources, and the main thread (or controlling thread) must trigger the exit conditions and wait until all the other thread are exit.

AfxPumpMessage() is using for?

I have a main thread and sub thread.
In subthread I sendmessage to main thread.
In main thread, I call this:
while( ::WaitForSingleObject(hThread, 0) == WAIT_TIMEOUT )
{
MSG message;
while( ::PeekMessage( &message, NULL , WM_MIN, WM_MAX, PM_NOREMOVE ) )
{
::AfxPumpMessage();
}
}
It works fine!. But I dont know How does AfxPumpMessage() work? How to it avoid deadlock?
Anyone help me? Thanks in advance.
Your code runs a busy loop. The outer while loop terminates when the thread is signaled. Until then the loop runs busy and dispatches messages. This is what allows the main thread to wait on the sub-thread, but also respond to the messages that the sub-thread sends.
In fact, the call to PeekMessage is rather pointless. It is pointless because AfxPumpMessage will do the same, and pump all queued messages.
As I said, your outer loop is a busy loop. You really don't want that. There's no point consuming CPU cycles to do nothing. Instead of WaitForSingleObject, you should use MsgWaitForMultipleObjects. This allows you to wait on the thread, and be able to dispatch messages.
Assuming that you don't want to deal with queued messages, and only want to dispatch the sent messages, your loop might look like this:
while( ::MsgWaitForMultipleObjects(1, &hThread, FALSE, INFINITE,
QS_SENDMESSAGE) == WAIT_OBJECT_0 + 1 )
{
MSG message;
::PeekMessage(&message, 0, 0, 0, PM_NOREMOVE);
}
This won't deal with an queued messages. If you do need to process those, then the loop would look a little different.

Why win32 thread doesn't exit automatically?

Background:
In my application written in C++, I create a worker thread which in turn creates two threads using CreateThread(). The two threads which worker thread creates, talk to WCF Service through a client which is implemented using Windows Web Services API which offers C/C++ application programming interface (API) for building SOAP based web services and clients to them. My application implements only the client using this API.
Problem:
The problem I'm facing is that all other threads exit gracefully, except the worker thread, as you can see yourself, in the image below that WorkerThreadProc uses no CPU cycles yet it doesn't exit. There are also few other threads running which are not created by me, but by the runtime.
The thread states are as follows (as reported by ProcessExplorer):
WorkerThreadProc is in Wait:WrUserRequest state.
wWinMainCRTStartup is in Wait:UserRequest state.
All TpCallbackIndependent are in Wait:WrQueue state.
What are they waiting for? What could be possible causes that I need to look into? Also, what is the difference between WrUserRequest and UserRequest? And what does WrQueue mean? I've absolutely no idea what is going on here.
Here is my WorkerThreadProc code. I've removed all the logging statements except the last one at the bottom of the function:
DWORD WINAPI WorkerThreadProc(PVOID pVoid)
{
//Initialize GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
Status status = GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
if ( status != Status::Ok )
{
return 1;
}
GuiThreadData *pGuiData = (GuiThreadData*)pVoid;
auto patternIdRequestQueue= new PatternIdRequestQueue();
auto resultQueue = new ResultQueue();
auto patternManager = new PatternManager(patternIdRequestQueue);
LocalScheduler *pScheduler = new LocalScheduler(resultQueue, patternManager);
bool bInitializationDone = pScheduler->Initialize(pGuiData->m_lpCmdLine);
if ( !bInitializationDone )
{
return 0;
}
//PatternIdThread
PatternIdThread patternIdThread(patternIdRequestQueue);
DWORD dwPatternIdThreadId;
HANDLE hPatternIdThread = CreateThread(NULL, 0, PatternIdThreadProc, &patternIdThread, 0, &dwPatternIdThreadId);
ResultPersistence resultPersistence(resultQueue);
DWORD dwResultPersistenceThreadId;
HANDLE hResultPersistenceThread = CreateThread(NULL, 0, ResultPersistenceThreadProc, &resultPersistence, 0, &dwResultPersistenceThreadId);
pScheduler->ScheduleWork(pGuiData->m_hWnd, pGuiData->m_hInstance, ss.str());
pScheduler->WaitTillDone();
patternIdThread.Close();
resultPersistence.Close();
delete pScheduler;
//Uninitialize GDI+
GdiplusShutdown(gdiplusToken);
dwRet = WaitForSingleObject(hPatternIdThread, INFINITE);
CloseHandle(hPatternIdThread);
dwRet = WaitForSingleObject(hResultPersistenceThread,INFINITE);
CloseHandle(hResultPersistenceThread);
SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0);
//IMPORTANT : this verbose message is getting logged!
T_VERBOSE(EvtSrcInsightAnalysis, 0, 0, "After sending message to destroy window");
delete patternManager;
delete patternIdRequestQueue;
delete resultQueue;
return 0;
}
Please see the T_VERBOSE macro, it is used to log verbose message. I see the message is getting logged, yet the thread doesn't exit!
EDIT:
I just commented the following line in my WorkerThreadProc, then worker thread exits gracefully!
SendMessage(pGuiData->m_hWnd, WM_CLOSE, 0, 0);
Does it mean that SendMessage is the culprit? Why would it block the thread the calling thread?
If we look at the docs for SendMessage, you can see this little quote:
To send a message and return immediately, use the SendMessageCallback
or SendNotifyMessage function. To post a message to a thread's message
queue and return immediately, use the PostMessage or PostThreadMessage
function.
and this:
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. However, the sending
thread will process incoming nonqueued messages while waiting for its
message to be processed. To prevent this, use SendMessageTimeout with
SMTO_BLOCK set. For more information on nonqueued messages, see
Nonqueued Messages.
so from this we can see SendMessage will block till the message is processed, which may somehow lead to a deadlock in your code, as the msgproc doesn't reside in your worker thread, leading to a context switch (which is only triggered when the thread's queue is pumped for messages). Try using PostMessage, which immediately returns.
EDIT: there is also a nice little piece of info here on message deadlocks from SendMessage

Child process receives parent's SIGINT

I have one simple program that's using Qt Framework.
It uses QProcess to execute RAR and compress some files. In my program I am catching SIGINT and doing something in my code when it occurs:
signal(SIGINT, &unix_handler);
When SIGINT occurs, I check if RAR process is done, and if it isn't I will wait for it ... The problem is that (I think) RAR process also gets SIGINT that was meant for my program and it quits before it has compressed all files.
Is there a way to run RAR process so that it doesn't receive SIGINT when my program receives it?
Thanks
If you are generating the SIGINT with Ctrl+C on a Unix system, then the signal is being sent to the entire process group.
You need to use setpgid or setsid to put the child process into a different process group so that it will not receive the signals generated by the controlling terminal.
[Edit:]
Be sure to read the RATIONALE section of the setpgid page carefully. It is a little tricky to plug all of the potential race conditions here.
To guarantee 100% that no SIGINT will be delivered to your child process, you need to do something like this:
#define CHECK(x) if(!(x)) { perror(#x " failed"); abort(); /* or whatever */ }
/* Block SIGINT. */
sigset_t mask, omask;
sigemptyset(&mask);
sigaddset(&mask, SIGINT);
CHECK(sigprocmask(SIG_BLOCK, &mask, &omask) == 0);
/* Spawn child. */
pid_t child_pid = fork();
CHECK(child_pid >= 0);
if (child_pid == 0) {
/* Child */
CHECK(setpgid(0, 0) == 0);
execl(...);
abort();
}
/* Parent */
if (setpgid(child_pid, child_pid) < 0 && errno != EACCES)
abort(); /* or whatever */
/* Unblock SIGINT */
CHECK(sigprocmask(SIG_SETMASK, &omask, NULL) == 0);
Strictly speaking, every one of these steps is necessary. You have to block the signal in case the user hits Ctrl+C right after the call to fork. You have to call setpgid in the child in case the execl happens before the parent has time to do anything. You have to call setpgid in the parent in case the parent runs and someone hits Ctrl+C before the child has time to do anything.
The sequence above is clumsy, but it does handle 100% of the race conditions.
What are you doing in your handler? There are only certain Qt functions that you can call safely from a unix signal handler. This page in the documentation identifies what ones they are.
The main problem is that the handler will execute outside of the main Qt event thread. That page also proposes a method to deal with this. I prefer getting the handler to "post" a custom event to the application and handle it that way. I posted an answer describing how to implement custom events here.
Just make the subprocess ignore SIGINT:
child_pid = fork();
if (child_pid == 0) {
/* child process */
signal(SIGINT, SIG_IGN);
execl(...);
}
man sigaction:
During an execve(2), the dispositions of handled signals are reset to the default;
the dispositions of ignored signals are left unchanged.