How can the exit code of the main thread be retrieved, after having run ShellExecuteEx() in asychronous mode?
The process exit code can simply be retrieved as follows:
SHELLEXECUTEINFO execInfo;
execInfo.cbSize = sizeof(SHELLEXECUTEINFO);
execInfo.fMask = SEE_MASK_NOASYNC;
ShellExecuteEx(&execInfo);
/* Get process exit code. */
DWORD processExitCode;
GetExitCodeProcess(execInfo.hProcess, &processExitCode);
But how can the exit code of the main thread be retrieved? What should be passed to GetExitCodeThread()?
The exit code of the main thread is equal to the exit code of the process IMHO.
In order to get the exit code of the primary process thread - one has to obtain its HANDLE. Unfortunately ShellExecuteEx doesn't return you this (it returns only the HANDLE of the newly created process).
One could also enumerate all the threads in a particular process and open their handles (OpenThread). Thus, you could create a process in a "suspended" state, get the handle of its only thread (which didn't start execution yet), and then go on.
Alas, ShellExecuteEx neither allows you to create a new process in a suspended state.
So that I don't see a clean way to achieve what you want. I'd suggest the following:
Why would you want the exit code of the primary thread anyway? Perhaps the exit code of the process will be enough?
Consider using CreateProcess. It has the needed functionality.
Some dirty tricks may help, like injecting DLLs into the newly created process (hooking) and etc.
Related
I use CreateProcess to start a .exe of mine. I want to know if everything worked fine or if it encouter errors when I tried to start this .exe.
From what I can tell, I need to use GetLastError(), but I tried to simulate an error in the process path but it return the same last error code.
So I want to catch if CreateProcess is successfull or not and if the process is done. What should I do to achieve that ?
Thanks.
All the information you are looking for is spelled out in the documentation for CreateProcess:
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Note that the function returns before the process has finished initialization. If a required DLL cannot be located or fails to initialize, the process is terminated. To get the termination status of a process, call GetExitCodeProcess.
If you need to wait for the target process to terminate, call WaitForSingleObject on the process handle returned in the PROCESS_INFORMATION filled out by the call to CreateProcess.
Since you control the target process, you are free to choose any scheme that allows you to determine success or failure from the process' exit code. You can call GetExitCodeProcess at any time after the process' handle transitioned to the signaled state, and before you call CloseHandle on it.
There are several approaches I can think of:
#1 - Enumeration
You can enumarate the processes and check if the PID is in the list. Check out EnumProcesses
#2 - Checking Exit Codes
You can use GetExitCodeProcess. It will return STILL_ACTIVE (259) if the process is still running
#3 - Process Handles
WaitForSingleObject uses a Process handle with the SYNCHRONIZE access right and returns 0 if the process is not running.
Note: You should not specify INFINITE for the dwMilliseconds parameter because the function would not return until the process state became signaled(process is terminated).
I had a process with C++ on windows 2008R2, there are several theads in it. During the process's startup, there is a chance that one of the thread will exit. I didn't get a way to detect what happens, any suggestions?
Based on my investigation, the thread just exit without an exception. Access to a null pointer can cause the similar issue, but I didn't find such a position in the process. In fact, it should be better if the process just crash, then I can get a dump file; but nothing happens, just one thread exit.
I had tried the tool user mode process dumper, but it cannot work on the windows version that this process is working on.
I had tried the tool process monitor to check the thread exit event, but the process monitor will throw an exception when I try to reproduce this issue by starting the process again and again.
Thanks in advance.
Found the root cause at last -- the string is accessed by more than one threads, and one thread just exit. String is not thread safe.
Process Monitor helped to get the thread exit call stack on a powerful host, this makes the root cause clear.
Thanks all for your suggestions.
I have a program (runs as a background process) in which I installed a hook to capture EVENT_SYSTEM_FOREGROUND events (i.e - when the user switches between windows). The callback which is registered for the hook basically logs what application (process exe filename) the user has switched from and which they have switched to.
I want to add some code to check if the application they have switched from is still active (if not we assume they have closed it and that is what has brought a new window into the foreground). I am testing for it's existence by trying to create a handle to the previous PID using OpenProcess
//Check prev pid still exists - if not, assume the previous app has been closed
HANDLE hPrevProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,g_prevPid);
if (hPrevProc==NULL){
prevProcStillRunning=false;
}
else{
CloseHandle(hPrevProc);
}
Assumptions with the code above:
g_prevPid is populated with a PID - I have verified this
prevProcStillRunning has been initialized to true
The problem with the code above is that for some reason, even when the user has exited an app (say notepad.exe for example). For up to 10 seconds after they have exited, this test still passes (i.e - hPrevProc gets initialised). Even though I can see in the task manager that the Notepad.exe process has dissapeared (and yes I only have one instance of it opened), somehow, the OpenProcess line still can get a handle on that PID. I am guessing that somehow the PID actually still exists but it may be in a state where its terminating. I have found that if this code is called a few more times, eventually it will return null.
I would like to find out a better way I can test whether hPrevProc is still acitive.
I tried to test this using the GetExitCodeProcess function but this seems to just give me the PID and I'm not even sure if that's the right approach in any case.
Any help appreciated.
The process subsists in the system after it terminates at least while there is an open handle to it.
The only foolproof method to know whether a process is still active is:
make sure the process cannot exit with code STILL_ACTIVE (259)
try to open the process (OpenProcess)-> if you cannot is is terminated
read the exit process code (GetExitCodeProcess) -> if it is not STILL_ACTIVE the process is terminated.
You code could become:
//Check prev pid still exists - if not, assume the previous app has been closed
HANDLE hPrevProc = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,false,g_prevPid);
if (hPrevProc==NULL){
prevProcStillRunning=false;
}
else{
DWORD cr;
if ((GetExitCodeProcess(hPrevProc, &cr) == 0) || (cr != STILL_ACTIVE)) {
prevProcStillRunning=false;
}
CloseHandle(hPrevProc);
}
Anyway, closing a GUI application involves different steps:
the GUI elements are destroyed
the message loop ends
eventually the application could do background operations (save state to file, etc.)
the main procedure returns an exit code
the system knows that the application is terminated
The event will be sent as soon as the main window will be closed, which can happen some time before the application actually stops. A good example for that is Firefox. If you close the window and immediately try to start a new process, you will get an error because even if the UI is gone, the process is not still terminated. What is worse, is that you can find applications that simply go into background when you close the UI, and allow user to open UI again through an action on an icon in the status area of the taskbar (Shell_NotifyIcon and its callback). This is common for services of other application working in background (network servers, firewalls, etc.). In that case, the UI is gone but the process will not terminate.
TL/DR: the time between the disparition of the UI and the termination of the process owning it is variable and depends on the system load and the background activity of the process after closing the UI. You can try to use a delay for that but I cannon guarantee anything about it...
Probably some process (maybe yours?) still holds a valid handle to this process. Until CloseHandle was called on all handles, system maintains internal record which allow to access its process data. This is important because as you say it must be possible to call GetExitCodeProcess on closed process, also someone might want to wait for it to stop with WaitForSingleObject.
Also be carefull with PIDs, they can be reused - so in theory you might call OpenProcess on some other newly opened process.
As for checking if given process is not a zombie, you might try enumerating top level windows with EnumWindows, and checking if any of them is associated with given PID (to get window's PID use GetWindowThreadProcessID).
I need to execute processes with still being in control of each process.
I want to create a class which stores the threads or pids or what ever is necessary to do so.
I currently have a program which executes one external application with the C function execvp and also loads the environment from a shell script. So my current program is blocking. But I need to be able to keep it freely running and only by time I terminate a currently running or start a new external application.
My current approach would be to create a thread, which uses the execve function. But then the thread would be blocking as far as I can see.
The code which might be in the thread (with variables then):
char *argv[] = { "/bin/bash", "-c", "myApplication", 0 };
execve(argv[0], &argv[0], environment.data());
The applications called are probably not fixed in the code their names will be given by an external setup file, including parameters.
Now my actual question, is there a better way to "manage" external applications like that in c++? Some ready solution (class, library)? And if not how do I terminate the thread if this is the actual way. Using the terminate call is said to be bad practice, that's what I often read.
I hope this is now specific enough for the forum, because I do not know how to get more specific anymore. If you need more hints what I want to create here, feel free to ask in the comments.
Update:
to DBus & others:
Additional information I do not wrote all of the processes I want to start!
So it will be used to start 3rd party applications, which even if I have the code, do not want to change.
You want to fork() before you exec. fork() is a function that creates a new process identical to the original caller of fork() running as a subprocess. The difference is that the parent process gets the child's pid as a return value and the child gets 0. The gist of what you want to do is this:
pid_t pid = fork();
if( pid == 0 )
{
// we're the child process
char *argv[] = { "/bin/bash", "-c", "myApplication", 0 };
int rc = execve(argv[0], &argv[0], environment.data());
// execve only returns if there was an error
// check 'errno' and handle it here
}
else if ( pid < 0 )
{
// pid is less than zero, we didn't successfully fork,
// there is no child process.
throw "error message";
}
// do whatever processing the parent does
More info is here. The kill() function isn't bad practice per se, if you want to quickly and gracefully end the subprocess you can write signal handlers in it, but you should be using something like dbus or zeromq to do proper interprocess communication. You want to tell the program to do something, not just tell it to die (usually what you want it to do if you're killing it).
NEVER USE execv functions in threads because the execve() system call overlays the current process image with a new process image.
The correct pattern if fork-exec or better vfork-exec. Extract from the manpage:
The vfork() system call can be used to create new processes without fully
copying the address space of the old process, which is horrendously inefficient in a paged environment. It is useful when the purpose of fork(2)
would have been to create a new system context for an execve(2). The
vfork() system call differs from fork(2) in that the child borrows the
parent's memory and thread of control until a call to execve(2) or an
exit (either by a call to _exit(2) or abnormally). The parent process is
suspended while the child is using its resources.
Using vfork shortly followed with execve, you avoid the copy of the original process image, and do not erase if with the new process, so the original process has the pid of its child and cat control it, look whether it has ended, send it signals and so on.
In my project, I have a several applications running.
One of them is a 'watchdog' application - an application that checks every time interval in an infinite loop weather the other applications (wards) are still running. In case a ward is no longer running - the watchdog restarts it.
I now want to extend functionality of the watchdog so that he will somehow become aware not only if a program stops running, but what exit code it returned when it did, and then act according to exit code.
You should already be checking whether the ward has terminated with a wait function like WaitForMultipleObjects, called on a handle to the ward process (which you acquired via CreateProcess or OpenProcess). Once you've detected a terminated process, pass that same process handle to GetExitCodeProcess and it will tell you the exit code.