0

I have write this code:

static int exec_prog(const char **argv)
{
pid_t   my_pid;
int   status, timeout /* unused ifdef WAIT_FOR_COMPLETION */;

if (0 == (my_pid = fork())) {
        if (-1 == execve(argv[0], (char **)argv , NULL)) {
                perror("child process execve failed [%m]");
                return -1;
        }
}

#ifdef WAIT_FOR_COMPLETION
timeout = 1000;

while (0 == waitpid(my_pid , &status , WNOHANG)) {
        if ( --timeout < 0 ) {
                perror("timeout");
                return -1;
        }
        sleep(1);
}

printf("%s WEXITSTATUS %d WIFEXITED %d [status %d]\n",
        argv[0], WEXITSTATUS(status), WIFEXITED(status), status);

if (1 != WIFEXITED(status) || 0 != WEXITSTATUS(status)) {
        perror("%s failed, halt system");
        return -1;
}

#endif
return 0;
}

How should I know the time of waitpaid finction (in seconds)? I wish the parent will wait for his child at most 5 second, i guess it 1000 loops but Im not sure....

Thanks!!

alk
  • 69,737
  • 10
  • 105
  • 255
LIMA
  • 125
  • 1
  • 1
  • 8
  • 2
    Your question is an [XY problem](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You are asking how to time waitpid when what you really want is to wait at most 5 seconds. Timing waitpid is totally the wrong way to go about achieving your real goal for many reasons (e.g. different computers will have different times). See the duplicate for suggestions on how to achieve your real goal. – kaylum Dec 03 '16 at 06:54
  • 3
    Possible duplicate of [Is there a version of the wait() system call that sets a timeout?](http://stackoverflow.com/questions/18476138/is-there-a-version-of-the-wait-system-call-that-sets-a-timeout) – kaylum Dec 03 '16 at 06:54
  • You should look into [proper C formatting](//prohackr112.tk/r/proper-c-formatting). Or learn how to [thoroughly obfuscate your code](//prohackr112.tk/r/proper-c-obfuscation). – MD XF Dec 03 '16 at 07:09
  • Iam not understand if this code wait 1 second until child is exited or wait until child is exited and then wait 1 second? while(waitpid(pid, &status, WNOHANG) == 0) { sleep(1); } – LIMA Dec 03 '16 at 07:16
  • sorry, Im not understand how to edit my code – LIMA Dec 03 '16 at 07:18
  • 1
    From the [waitpid man page](https://linux.die.net/man/2/waitpid): `WNOHANG` means "return immediately if no child has exited". So that code checks for any exited child. If none then sleep 1 second and try again. – kaylum Dec 03 '16 at 07:52
  • the function: `fork()` has three return conditions: failure (<0) child (==0) and parent (>0). The posted code is treating a failure as it it were a parent. That is an error – user3629249 Dec 03 '16 at 07:55
  • the code must not exit before the child exits. Otherwise the child process becomes a `zombie`. Zombie processes are very difficult to eliminate without rebooting the computer. – user3629249 Dec 03 '16 at 07:57
  • the posted code will execute itself. This means that each process will (again) create a child process, which will create a child process...... I.E. this will never end until the OS runs out of available process slots. And none of those child processes will ever exit. Strongly suggest having the `execve()` execute something else. – user3629249 Dec 03 '16 at 08:09
  • Why do you make the code loop 1000 times waiting 1 second on each iteration making it wait 1000s in total before timing-out, if you just want to have it wait 5s? – alk Dec 03 '16 at 12:28
  • the 1000 loops is guess for 5 second, my goal is to wait 5 second until the child is finished. I dont know how – LIMA Dec 03 '16 at 12:54

1 Answers1

0

Super old question, but I created this solution (different timeframe):

constexpr std::chrono::milliseconds waitTimeoutCheck {10};
constexpr std::chrono::milliseconds waitTimeoutTime {100};
void stopChild(pid_t pid)
{
    std::cout << "Sending SIGTERM" << std::endl;
    kill(pid, SIGTERM);

    int status;
    int retVal;
    int loopCount {0};
    std::chrono::milliseconds totalTimeout {waitTimeoutTime};
    do
    {
        ++loopCount;
        retVal = waitpid(pid, &status, WNOHANG);
        if (retVal == 0)
        {
            std::this_thread::sleep_for(waitTimeoutCheck);
            totalTimeout -= waitTimeoutCheck;
        }
    } while (retVal == 0 && totalTimeout > std::chrono::milliseconds(0));

    if (retVal == 0)
    {
        // timed out without child ending
        std::cout << "Did not respond to SIGTERM, sending SIGKILL" << std::endl;
        kill(pid, SIGKILL);
        // Block until killed
        waitpid(pid, &status, 0);
    }
    else
    {
        std::cout << "Program responded to SIGTERM in " << std::to_string(loopCount) << " tries." << std::endl;
    }
}