Reputation: 467
I'm looking how I can get exit code from non-child process.
As we all know there are few functions to work with child processes such as wait/waitpid. With this function we can wait until child process will be closed and get exit error code. But this works only with child processes.
Actually I'm looking for Windows analogue of GetExitCodeProcess. In Windows we can open process by calling OpenProcess
and then work directly with returned handle. So we can call GetExitCodeProcess
function and retrieve status.
Is there something same in Linux for working with non-child processes?
Upvotes: 1
Views: 1353
Reputation: 6342
There are several ways to do this, each with its own caveats. At first, I attempted to rank these from "best" to "worst" according to a very arbitrary criteria that suits the needs that you and I share, but then I realized that cross-platform compatiblity -- and even compatiblity with relatively recent Linux kernels -- was non-existent and, as such, they are presented in a random order. Here are the criteria, which are derived from the criteria you explicitly mentioned or may benefit from:
SIGTERM
, SIGKILL
, etc.)? note: you didn't mention this, but if you want to know how the process exited, the return code isn't the only thing to consider!setcap
could do thisOne very intrusive way to accomplish this is with ptrace
. However, on most systems, not only do you probably need root, but the implementation is incredibly inconsistent. See, for example, this repository, which says:
ptrace
on Linux is wonderful. It's simple, it's functional and easy to use.ptrace
on MacOS isn't.
Interestingly, on OSX, I was able to attach to the process using ptrace's PTRACE_ATTACH
(which stops the process), then use waitpid
to wait on it, then send a ptrace PTRACE_CONT
message (to continue), then wait on it again (until it exits). I did not expect this to work, but it does, and I can get the return status. waitpid
is supposed to only be for child processes. I believe this behavior is undocumented. It may work for other BSD-like systems. Unfortunately it requires root, even when the process is your own.
Another way on BSD-systems is using kqueue. You want the EVFILT_PROC
event filter and the filter flag NOTE_EXIT
. See the man page on kqueue for details. I am using this successfully on MacOS as long as I'm only trying to monitor processes that I launched. This actually works perfectly and checks many of the boxes, except that it's not totally cross-platform (no Linux support) and it only gives you the exit status. You won't find information about a core dump or a signal causing termination.
This is implemented in the Linux kernel in cn_proc.c. Netlink is used to communicate directly with the kernel from userspace using sockets. This answer by @agile explains what you need to know. Unfortunately, Netlink is a Linux feature with no cross-platform compatibility. An example of collecting all of the important data (including which signal lead to process termination) can be found in this line of stormc's waitforpid repo on GitHub
Procfs is not a good solution because as soon as the process exits, the return code (along with the rest of the directory representing the PID) is gone. But in a pinch, you could either poll or use inotify
(which does work on procfs!) to at least figure out when the process has exited. You could do the same thing by sending a NULL
signal to the process and, if it succeeds, it is still alive.
Upvotes: 0
Reputation: 20842
There is no POSIX or otherwise standard UNIX / Linux call to do what you ask, that I know of, but you can possibly accomplish it on Linux (or other UNIX) using the procfs. Many non-standard extensions were innovated with the procfs.
If the parent has not yet waited on the child, the return code may still be around.
See: Linux, where are the return codes stored of system daemons and other processes?
Upvotes: 1