Determine if my application terminated due to a call to _exit() - c

I can determine if my application last terminated due to a call to exit() by using atexit or a destructor function. Is there any way to determine if my application last terminated due to _exit()?

From the man page
The function _exit() terminates the calling process "immediately".
Any open file descriptors belonging to the process are closed; any children of the process are inherited by process 1, init, and the process's parent is sent a SIGCHLD signal.
The value status is returned to the parent process as the process's exit status, and can be collected using one of the wait(2) family of calls.
and you cannot expect atexit() to be called. However, similarly to exit, a status is set and returned from _exit that you might want to test from a calling script, for instance. (e.g. exit(0); and _exit(1);, if the returned value is 1 you know that _exit was used, not exit.)

Related

What happens to signal handler after exec call? [duplicate]

I wrote a signal handler for a process, and fork() after that, the signal handler will be applied to both parent and child processes. If I replace the child process with "exec", the signal handler is no more.
I know this happens because "exec" call will overwrite the child process address space with it's own.
I just want to know if there is a way to make signal handler work even after "exec" call ?
No. From the man pages:
execve() does not return on success, and the text, data, bss, and stack of the calling process are overwritten by that of the program loaded. The program invoked inherits the calling process's PID, and any open file descriptors that are not set to close on exec. Signals pending on the calling process are cleared. Any signals set to be caught by the calling process are reset to their default behaviour. The SIGCHLD signal (when set to SIG_IGN) may or may not be reset to SIG_DFL.
In fact, if the signal handler were still active after the code had been replaced with some very different code, you could expect all sorts of mayhem when the signal occurred. The signal handler is, after all, just an address to call when something happens (discounting SIG_IGN and SIG_DFL for now). Who knows what piece of code would be at that address when you replace the entire text segment?

On Windows do I *have to* call WaitForSingleObject() after calling CreateProcess()?

On Linux, I have to call wait() after fork() on the parent process, otherwise the child process will stay zombie after completion until the parent process completes.
I wonder whether I must follow similar steps on Windows,
i.e. whether I must call WaitForSingleObject() after calling CreateProcess().
I know that Windows' CreateProcess() is different from Linux's fork() and it seems that 'zombie' is a UNIX/Linux concept that does not exist on Windows. But maybe I still must call WaitForSingleObject() to free some OS resources allocated for CreateProcess(), similar to the Linux case.
If CreateProcess succeeds you must close the two handles in PROCESS_INFORMATION but you don't have to wait for the child process first, the handles can be closed at any point if you don't need them.
A open handle to a process will keep the process object alive in a zombie state after it has finished running.

exit(...): Will it cause parent process to terminate?

If I call exit(1) in the child process, will this action cause parent process to terminate as well? Or simply only child process is terminated by exit(1)?
man exit
This shows
The exit() function causes normal [current/child] process termination and the value of [the exit] status is returned to the parent [process] (see wait(2)).
...
After exit(), the exit status must be transmitted to the parent process. There are three cases. If the parent has set SA_NOCLDWAIT, or has set the SIGCHLD handler to SIG_IGN, the status is discarded. If the parent was waiting on the child, it is notified of the exit status.
In both cases the exiting process dies immediately. If the parent has not indicated that it is not interested in the exit status, but is not waiting, the exiting process turns into a "zombie" process (which is nothing but a container for the single byte representing the exit
status) so that the parent can learn the exit status when it later calls one of the wait(2) functions.
exit does not cause the parent to also exit. It causes normal process termination for the current process.
No, the exit() does not terminate the parent process. The exit() function will terminate the current process, and return the exit code to the parent process. So, if you use exit(1), then the exit code 1 will be returned to the parent process.

Developing a correct understanding of waitpid() and getpid()

I am learning about forks, execl and parent and child processes in my systems programming class. One thing that is confusing me is waitpid() and getpid(). Could someone confirm or correct my understanding of these two functions?
getpid() will return the process ID of whatever process calls it. If the parent calls it, it returns the pid of the parent. Likewise for the child. (It actually returns a value of type pid_t, according to the manpages).
waitpid() seems more complex. I know that if I use it in the parent process, without any flags to prevent it from blocking (using WNOHANG), it will halt the parent process until the child process terminates. I'm a little unsure as to how waitpid() manages all this, however. waitpid() also returns pid_t. What is the value of the pid_t waitpid() returns? How does this change depending on whether or not a parent or child calls it, and whether or not a child process is still running, or has terminated?
Your understanding of getpid is correct, it returns the PID of the running process.
waitpid is used (as you said) to block the execution of a process (unless
WNOHANG is passed) and resume execution when a (or more) child of the process
ends. waitpid returns the pid of the child whose state has changed, -1 on
failure. It also can return 0 if WNOHANG has specified but the child has not
changed the state. See:
man waitpid
RETURN VALUE
waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG
was specified and one or more child(ren) specified by pid exist, but have not yet changed state,
then 0 is returned. On error, -1 is returned.
Depending on the arguments passed to waitpid, it will behave differently. Here
I'l quote the man page again:
man waitpid
pid_t waitpid(pid_t pid, int *wstatus, int options);
...
The waitpid() system call suspends execution of the calling process until a child specified by pid argument
has changed state. By default, waitpid() waits only for terminated children, but this behavior is modifiable
via the options argument, as described below:
The value of pid can be:
< -1: meaning wait for any child process whose process group ID is equal to the absolute value of pid.
-1: meaning wait for any child process.
0: meaning wait for any child process whose process group ID is equal to that of the calling process.
> 0: meaning wait for the child whose process ID is equal to the value of pid.
The value of options is an OR of zero or more of the following constants:
WNOHANG: return immediately if no child has exited.
WUNTRACED also return if a child has stopped (but not traced via ptrace(2)).
Status for traced children which have stopped is provided even if this option is not specified.
WCONTINUED (since Linux 2.6.10) also return if a stopped child has been resumed by delivery of SIGCONT.
I'm a little unsure as to how waitpid() manages all this
waitpid is a syscall and the OS handles this.
How does this change depending on whether or not a parent or child calls it, and whether or not a child process is still running, or has terminated?
wait should only be called by a process that has executed fork(). So the parent
process should cal wait()/waitpid. If the child process hasn't called
fork(), then it doesn't need to call either one of these functions. If however
the child process has called fork(), then it also should call
wait()/waitpid().
The behaviour of these function is very well explained in the man page, I quoted the important parts of it. You should read the whole man page
to get a better understanding of it.
waitpid "shall only return the status of a child process" (from the POSIX spec). So the pid_t waitpid returns belongs to one of the current or former children of the process calling waitpid. For example, if a child has recently terminated, it returns that child's PID.
waitpid is only useful when called from a parent process. If called from a process that does not have any children, it returns ECHILD.
waitpid can check the status of children that have terminated, or that has recently stopped or continued (e.g., ^Z from a shell). The various pid/option argument combinations in the spec tell you the various types of information you can return. For example, the WCONTINUED option requests status of recently-continued children instead of recently-terminated children.

Alternatives to popen/pclose?

I'm writing a program that has to execute other external processes; right now the program launches the processes' commandlines via popen, grabs any output, and then grabs the exit status via pclose.
What is happening, however, is that for fast-running processes (e.g. the launched process errors out quickly) the pclose call cannot get the exit status (pclose returns -1, errno is ECHILD).
Is there a way for me to mimic the popen/pclose type behavior, except in a manner that guarantees capturing the process end "event" and the resultant return code? How do I avoid the inherent race condition with pclose and the termination of the launched process?
fork/exec/wait
popen is just a wrapper to simplify the fork/exec calls. If you want to acquire the output of the child, you'll need to create a pipe, call fork, dup the child's file descriptors to the pipe, and then exec. The parent can read the output from the pipe and call wait to get the child's exit status.
You can use vfork() and execv().

Resources