Get the status of a specific PID

A simple problem, but I have not found an answer yet. Given a specific PID, can I determine if this process is active? I am working on a C program and it makes me crazy. I read somewhere that I kill(pid,0)would do the trick, but this returns 0 regardless of whether the process is running or not (or it seems).

Any clues?

Additional Information: The process that interests me is the child initiated fork(). The baby process should end when it reaches approval. exit(0).At least what I expected ... apparently this is not happening.

Additional additional information: A child process created with the help fork()executes a system command, which may vary depending on the end user. All this is part of the batch process, so there is no way to jump over and fix something. One of the tasks that this child process should perform, is to establish a connection with a remote server to store some documents there. It could be another Linux machine, or it could be Win Server (or maybe something else). For this reason, I do not want to wait for the baby process. I would like the parent to wait a certain period of time (say 10 seconds), and then kill the child process if it has not already completed by then. Similarly, I do not want the parent process to wait 10 seconds if the child completes its task in 3 milliseconds.

It seems I am not the first to encounter this problem.

+4
source share
5 answers

You are looking for a waitpid that will return status information for a given PID.

/proc/[pid]/stat linux .

IMO.

-:

. waitpid ( WNOHANG) , , .

-:

. waitpid WNOHANG , . , , , , , .

, waitpid - , . , 10 , , .

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.
     }
 }
+4

Linux , . Linux , wait()-like. , , init child init wait()-like .

, , wait()-like, - EXIT_ZOMBIE. kill(pid, 0) . pid.

man 3 exit wait(2) .

kill(pid, 0). , , . , , wait(), .

kill(), 0. , kill -1 errno set (ESRCH). , , wait(), . , , .

? pid () :

cat /proc/[pid]/status | grep "State"

Z (man 5 proc).

, !

+2

- - .

  • . SIGCHLD , , , , . wait waitpid, , . wait (waitpid) .

  • (, itimer, timer_create, alarm ..). , , kill . , . ( ) , .

+1

fork() . , . , (, ). , , , stopOnSignal kill() . , kill() , getppid().

, ( exec() 10.01.2014):

#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#include <bits/signum.h>

static bool stopOnSignal = false;



uint32_t clockedMilliseconds(clock_t t1, clock_t t2)
{
    if (t2 > t1) { return (t2 - t1) / (CLOCKS_PER_SEC/1000); }
    else /* the time has wrapped around since the values were set */
    { return t2 / (CLOCKS_PER_SEC/1000); }
}



void signalHandler(int signum)
{
   printf("Caught signal %d\n",signum);
   stopOnSignal = true;
}



int main (int argc, char *argv[])
{
    pid_t cpid;
    char * mstr;
    int rc = -999999;
    int krc = 0;
    uint32_t timeoutWait =  10000 ; // default 10 secs
    int count = 0;
    int loops = 0;

    signal(SIGUSR1, signalHandler);

    if (argc < 2) {
        printf("usage: ./sigparent sleep-milliseconds [timeout-milliseconds]");
        exit -1;
    }

    cpid = fork();
    if (cpid == -1) {
        printf("%d : failed to start child process.\n", errno);
        perror("fork");
        exit(-1);
    }

    if (cpid == 0) { /* Code executed by child process */

        execl("sleeping_child", argv[1],(char *) NULL);

    }
    else { /* Code executed by parent */

        if (argc > 2) sscanf(argv[2],"%d",&timeoutWait);
        clock_t t1 = clock();
        clock_t t2;

        do { /* loop until child process ends or timeout limit is reached */

            if (count < 100000) count++;
            else {
               loops++;
               printf("loops of 100000 duration = %d \n", loops);
               count = 0;
            }
            t2 = clock();

            if ( clockedMilliseconds(t1, t2) > timeoutWait) {
                krc = kill(cpid,9);
                rc = 3;
                break;
            }
            if ( stopOnSignal == true ) {
                //krc = kill(cpid,9);
                rc = 0;
                break;
            }
        } while (true);

        if (rc == -999999) {
                printf("process failed horribly!\n");
        }
        else if (rc == 3) {
            if (krc == 0){ /* child process timed out */
                printf("TIMEOUT, waiting %d ms on pid %d\n",
                       timeoutWait, cpid);
            }
            else { /* attempted timeout failed - result is unpredictable */
                printf("%d : attempted TIMEOUT failed.\n", errno);
                perror("kill");
            }
        }
        else { /* rc == 0 */
             printf("child process ended normally.\n");
        }
    }
    exit(0);
}

, - . - sigparent.c. sleep_child.c.

/* sleeping_child */
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>

int main (int argc, char * argv[]) {

    int rc = 0;
    int millis;

    if (argc > 2) sscanf(argv[2],"%d",&millis);
    else millis = 2000;

    rc = usleep(millis * 1000);
    printf("slept for %d milliseconds\n",millis);
    printf("parent is %d \n", getppid());
    kill(getppid(),SIGUSR1);
    return(rc);
}

sleep_child , bash. , :

# to compile...
gcc -o sleeping_child sleeping_child.c
gcc -o sigparent sigparent.c
# to let the child terminate, set the second parameter to greater than the first...
./sigparent 1000 3000
# to cause the parent to timeout the child make the first parameter greater...
./sigparent 10000 3000

Duck . , , . , waitpid().. , .

0

, , . , itimer, , timer_create alarm. , ( - ), .

#define _POSIX_C_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <sys/types.h>

pid_t cpid;    
volatile sig_atomic_t done = 0;

void alarmHandler(int signum)
{
    if (kill(cpid, SIGTERM) != -1)
        printf("kill signal sent to child from parent\n");
    else
        if (errno == ESRCH)
            printf("kill could not find child, must already be dead\n");
        else
        {
            perror("kill");
            exit(EXIT_FAILURE);
        }
}

void childHandler(int signum)
{
    pid_t childpid;
    int status;

    while ((childpid = waitpid( -1, &status, WNOHANG)) > 0)
    {    
        if (WIFEXITED(status))
            printf("Child %d exited naturally\n", childpid);

        if (WIFSIGNALED(status))
            printf("Child %d exited because of signal\n", childpid);
    }

    if (childpid == -1 && errno != ECHILD)
    {
        perror("waitpid");
        exit(EXIT_FAILURE);
    }

    done = 1;
}

int main (int argc, char *argv[])
{
    int sleepSecs;
    int timeoutSecs;

    if (argc < 3)
    {
        printf("\nusage: %s sleep-seconds timeout-seconds\n\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    sscanf(argv[1], "%d", &sleepSecs);
    sscanf(argv[2], "%d", &timeoutSecs);

    signal(SIGCHLD, childHandler);
    signal(SIGALRM, alarmHandler);

    if ((cpid = fork()) == -1)
    {
        printf("%d : failed to start child process.\n", errno);
        perror("fork");
        exit( -1);
    }

    if (cpid == 0) //child
    {
        execl("./sleeping_child", "./sleeping_child", argv[1], (char *) NULL);

        perror("execl");
        exit(EXIT_FAILURE);
    }
    else //parent
    {
        alarm(timeoutSecs);

        while (! done)
        {
            sleep(1); // or do something useful instead
        }

        exit(0);
    }
}

And the children's program should not do anything special to die.

/* sleeping_child */
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

int main (int argc, char * argv[]) 
{
    printf("child will sleep for %s seconds\n", argv[1]);

    sleep(atoi(argv[1]));

    exit(0);
}

Some examples of runs are as follows

$ simpleReap 3 1
child will sleep for 3 seconds
kill signal sent to child from parent
Child 5095 exited because of signal

$ simpleReap 1 3
child will sleep for 1 seconds
Child 5097 exited naturally
0
source

All Articles