I have a Win32 program. This program creates a process with CreateProcess function to run another program. I want to parent process to be closed, if the child process was closed or crashed for any reason.
How can I do it?
You can use the WaitForSingleObject function on the created process' handle, like so:
STARTUPINFO si {sizeof(si)};
PROCESS_INFORMATION pi {};
CreateProcessW(/*your arguments here*/);
WaitForSingleObject(pi.hProcess, INFINITE);
Note that if you do use INFINITE as the wait time, the function blocks until the process terminates. If you want the parent process to be doing other things in the mean time, it's best to have that code in a separate thread.
If you want the parent process to be a complete wrapper for the created process, use GetExitCodeProcess when you're done to obtain the child process' exit code.
DWORD dwExit;
GetExitCodeProcess(pi.hProcess, &dwExit);
This code was just a simple example. All three functions I mentioned in my answer can fail, and robust code would check their return values and act accordingly in the case of failure.
Related
I'm writing a shell in cpp and I was hoping to get some advice. I have a command that will do an exec in the background, and I'm trying to keep track of which background processes are still running. I thought maybe I could keep track of the PID and do a string find on /proc/, but it seems to stay longer than it should. I'm testing it by using the sleep command, but it seems to always linger around wherever I look long after it should've finished. I'm probably just not doing the right thing to see if it is still running though.
Thanks in advance for any help.
Assuming you are spawning off the child process via fork() or forkpty(), one reasonably good way to track the child process's condition is to have the parent process create a connected-socket-pair (e.g. via socketpair()) before forking, and have the child process call dup2() to make one end of that socket-pair its stdin/stdout/stderr file descriptor, e.g.:
// Note: error-checking has been removed for clarity
int temp[2];
(void) socketpair(AF_UNIX, SOCK_STREAM, 0, temp);
pid_t pid = fork();
if (pid == 0)
{
// We are the child process!
(void) dup2(temp[1], STDIN_FILENO);
(void) dup2(temp[1], STDOUT_FILENO);
(void) dup2(temp[1], STDERR_FILENO);
// call exec() here...
}
The benefit of this is that now the parent process has a file descriptor (temp[0]) that is connected to the stdin, stdout, and stderr of the child process, and the parent process can select() on that descriptor to find out whenever the child process has written text to its stderr or stdout streams, and can then read() on that file descriptor to find out what the child process wrote (useful if you want to then display that text to the user, or if not you can just throw the read text away), and most importantly, it will know when the child process has closed its stderr and stdout streams, because then the parent process's next call to read() on that file descriptor will indicate 0 aka EOF.
Since the OS will automatically close the child process's streams whenever it exits for any reason (including crashing), this is a pretty reliable way to get notified that the child process has gone away.
The only potential gotcha is that the child process could (for whatever reason) manually call close(STDOUT_FILENO) and close(STDERR_FILENO), and yet still remain running; in that case the parent process would see the socket-pair connection closing as usual, and wrongly think the child process had gone away when in fact it hadn't. Fortunately it's pretty rare for a program to do that, so unless you need to be super-robust you can probably ignore that corner case.
On a POSIX-like system, after you create any child processes using fork, you should clean up those child processes by calling wait or waitpid from the parent process. The name "wait" is used because the functions are most commonly used when the parent has nothing to do until a child exits or is killed, but waitpid can also be used (by passing WNOHANG) to check on whether a child process is finished without making the parent process wait.
Note that at least on Linux, when a child process has exited or been killed but the parent process has not "waited" for the child, the kernel keeps some information about the child process in memory, as a "zombie process". This is done so that a later "wait" can correctly fetch the information about the child's exit code or fatal signal. These zombie processes do have entries in /proc, which may be why you see a child "stay longer than it should", if that's how you were checking.
I want to write a program in C++ that can open a .exe program and I want to know when it's close by the user. I know that I can open a program by this code:
system ("start C:\\AAA.exe");
However I don't know how can I check if the program closed.
On Windows if you use CreateProcess() instead of system() to start a new process. Simplified code:
PROCESS_INFORMATION processInformation;
CreateProcess(..., &processInformation);
In PPROCESS_INFORMATION you find its handle. With its handle you can wait it's terminated (to mimic how system() works):
WaitForSingleObject(processInformation.hProcess, INFINITE);
Or periodically check its status getting its exit code (if any, see also How to determine if a Windows Process is running?) if your code has to run together with child process:
DWORD exitCode;
BOOL isActive = STILL_ACTIVE == GetExitCodeProcess(processInformation.hProcess, &exitCode);
Don't forget to close handle (even if process already terminated):
CloseHandle(processInformation.hProcess);
Note that with that code you don't know the reason process terminated. It may be because user closed its window, because it terminated by itself or because it crashed. For a GUI application you can hook its main window messages looking for WM_CLOSE (to detect user actions), WM_QUIT (application did it) and attaching an handler with SetUnhandledExceptionFilter() (to detect unhandled errors). It's not 100% reliable but it may be material for another question...
Calling system ("C:\AAA.exe"); you can block until process AAA.exe finished.
If it is not acceptable, you can call system ("C:\AAA.exe"); in separate thread, and check is it finished or not.
#include <thread>
void threadRoutine()
{
::system("C:\AAA.exe");
}
int main()
{
std::thread systemCall(threadRoutine);
//do some work here
systemCall.join();
//you are sure that AAA.exe is finished
return 0;
}
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.
I have a simple program (in C) that create two child process, wait on an inherited pipe each, and put the output in a file.
Everything works well, except that after some write/read cycle on the two pipe, when the child ends, the call to ReadFile block, waiting for data on the pipe. I use the following pattern:
...
//create pipe1
CreatePipe(&hReadDup,&hWrite,&saAttr,0);
DuplicateHandle(GetCurrentProcess(),hReadDup,GetCurrentProcess(),&hRead,0,FALSE,DUPLICATE_SAME_ACCESS);
CloseHandle(hReadDup);
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdOutput = hWrite;
CreateProcess( NULL,
const_cast<LPWSTR>(cmd2.c_str()), //the command to execute
NULL,
NULL,
TRUE,
0,
NULL,
NULL,
&si, //si.
&pi
);
...
CloseHandle(hWrite); // EDIT: this was the operation not properly done!
while(cont){
...
cont = ReadFile(hRead,buf,50, &actual,NULL);
...
}
...
The last call (after child process exit) block.
Idea of why (and, if not, how to debug this)?
I found out the solution myself (wich actually was a coding error).
I wasn't closing the parent's write handle of the pipe properly (hWrite), so, the synchronous ReadFile wasn't able to report me back the child process termination.
If somebody has the same problem, make sure you close the inheritable handle of the pipe before starting the I/O operation on that pipe (as MSDN reports, cannot find again were).
You are calling ReadFile() in synchronous mode. As long as the pipe is open, ReadFile() will block waiting for more data. If you leave open the process and thread handles that CreateProcess() returns to you, that will prevent the child process from fully exiting, so the pipe may not get closed on the child end. Before entering your reading loop, close the handles that CreateProcess() returns, allowing the pipe to close properly when the child process fully terminates, and then ReadFile() can report an error back to you when it can't read from the pipe anymore. Alterntively, switch to overlapped I/O on the pipe so you can monitor the child process with WaitForSingleObject() or GetExitCodeProcess() while the loop is running so you can detect when the child process terminates regardless of the pipe state.
In your case all good, you had access to both processes on the pipe. If however you did not, or just wanted to interrupt the ReadFile call, then CancelSynchronousIo is your friend: https://msdn.microsoft.com/en-us/library/windows/desktop/aa363789(v=vs.85).aspx
I am using CreateProcess function for creating the process, is there any option to get the current state of the process (running or not). Kindly guide me how can I make it possible.
Use OpenProcess function with that dwProcessId if it returns NULL Process is not running otherwise it will return handle to that process
Create process returns a handle to the process in PROCESS_INFORMATION structure, you can use this with something like GetExitCodeProcess to work out if it is still running, or you can use the wait functions to wait for it to exit.