Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get the status of a specific PID

Tags:

c

linux

pid

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.

like image 757
Achim Schmitz Avatar asked Jan 08 '14 15:01

Achim Schmitz


People also ask

How do you get the details of a particular process in the terminal?

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.

What is the command used to check the PID?

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.


2 Answers

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!

like image 95
Paulo Bu Avatar answered Oct 25 '22 02:10

Paulo Bu


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.
     }
 }
like image 43
Devolus Avatar answered Oct 25 '22 03:10

Devolus