Simple problem but I haven't found an answer, yet. Given a specific PID, can I determine whether that process is active? I'm working on a C program and this is driving me nuts. I read somewhere that kill(pid,0)
would do the trick, but this returns 0 regardless of whether the process is running or not (or so it seems).
Any hints?
Additional info:
The process I'm interested it is a child initiated by a fork()
.
The child process should terminate when it reaches the statement exit(0).
At least that's what I expected... apparently it doesn't.
Further additional info:
The child process that is created with a fork()
executes a system command which can be different depending on the end-user. The whole thing is part of a batch process, so there's no chance to jump in and fix something. One of the tasks that this child process may have to perform is to establish a connection to a remote server in order to store some documents there. This might be another Linux machine or it might be a Win Server (or possibly something else). For this reason I don't want to wait for the child process. I would like the parent to wait a specific length of time (say 10 seconds) and then kill the child process if it hasn't completed by then. By the same token, I don't want the parent process to wait 10 seconds if the child completed its task in 3 milliseconds.
It seems I'm not the first to have this problem.
Open the terminal window on Linux. For remote Linux server use the ssh command for log in purpose. Type the ps aux to see all running process in Linux. Alternatively, you can issue the top command or htop command to view running process in Linux.
Press Ctrl+Shift+Esc on the keyboard. Go to the Processes tab. Right-click the header of the table and select PID in the context menu.
Linux doesn't remove the process descriptor once terminated, because parents could need their info later. Linux only removes them completely when the parent issue a wait()-like
system call on it. Normally this is done by its father, but if the process is orphan, it becomes init
's child and init
eventually issues wait()-like
system calls to kill zombie process.
Having said that, until the father issues a wait()-like
call, the child's process descriptor is still allocated with EXIT_ZOMBIE
status. This is why kill(pid, 0)
works ok. It is able to find the process descriptor with pid
field.
man 3 exit
expands on this further and explains the relationship with wait(2)
and with zombies processes.
Regarding to kill(pid, 0)
. It can be used to figure out if a process exists or don't. But it doesn't tell you if is running or waiting for a parent to issue a wait()
system call to sweep it from kernel's memory.
If it exists kill()
will return 0. If it doesn't, kill will return -1
with proper errno
set (ESRCH
). If you fork a process, while the father exists, it's its responsibility to issue a wait()
to get their children termination info. If it doesn't, children will be wandering around until father dies.
Want to make sure? Figure out the pid
of the child (allegedly) zombie and issue this command:
cat /proc/[pid]/status | grep "State"
It should show a Z
for zombie (man 5 proc
).
Hope this helps!
You are looking for waitpid which will return status information for a given PID.
For an unrelated process you can use /proc/[pid]/stat
in linux and read the output.
Regarding the updated information
There are two scenarios IMO.
First:
The child process is done quickly. Use waitpid (with WNOHANG) and get it's status, then you know how it terminated and that it actually terminated.
Second:
The child process is running. Use waitpid with WNOHANG and check if it is still running. If not do whatever else the parent needs to do, after sufficient time has elapsed, and the child still runs, you can kill it, or do whatever your design sees fit as an appropriate response.
In either way, waitpid is exactly what you need here. The pseudocode just demonstrartes, that you can do other stuff in between and that you don't need to wait 10 seconds even if the child is terminated earlier, bec ause polling like this is not really appropriate.
psuedocode:
pid_t pid;
pid = fork();
while(1)
{
if(pid == 0)
{
if(status = waitpid(pid, WNOHANG))
{
if(status != exited)
{
if(checkExpiryTime() == true)
kill(pid, SIGKILL);
else
sleep(x); // or whatever is appropriate in your case.
}
}
}
else
{
// do childstuff here.
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With