How to wait time out without killing a child?

I know a lot of questions regarding waitpid and timeouts, but they all cover this, killing a child from an alarm handler.

This is not what I want, I want the process to execute, but send it from waitpid.

The problem with the litter that I am trying to solve is the daemon process with the main loop that processes the queue. Tasks are processed in turn.

If the task hangs, the entire main loop freezes. Getting around this fork() and waitpid seemed like an obvious choice. However, if the task hangs, the loop freezes.

I can think of workarounds when I do not use waitpid at all, but I will have to monitor the running processes in a different way, because I still want to process one task at a time in parallel with possible possible freezing of tasks.

I could even kill a task, but I would like to run it to check what exactly is going wrong. A leak handler is also possible that provides some debugging information.

In any case, the most convenient way to solve this problem is to waitpid timeout, if you have one.

Edit:

This is how I used fork () and waitpid, and it can be clearer what is meant by a child.

 my $pid = fork(); if ($pid == 0){ # i am the child and i dont want to die } elsif ($pid > 0) { waitpid $pid, 0; # i am the parent and i dont want to wait longer than $timeout # for the child to exit } else { die "Could not fork()"; } 

Edit:

Using waitpid WNOHANG does what I want. Is this use good practice or will you do it differently?

 use strict; use warnings; use 5.012; use POSIX ':sys_wait_h'; my $pid = fork(); if ($pid == 0){ say "child will sleep"; sleep 20; say "child slept"; } else { my $time = 10; my $status; do { sleep 1; $status = waitpid -1, WNOHANG; $time--; } while ($time && not $status ); say "bye"; } 
+4
source share
3 answers

If the task hangs, the entire main loop freezes. To get around this fork () and waiting seemed an obvious choice. However, if the task hangs in a loop hangs.

Use waitpid with the WNOHANG option. Thus, this will not lead to the suspension of the parent process and will immediately return 0 when the child has not yet left. In your main cycle, you will have to periodically poll all the children (tasks).

+7
source

Instead of periodically switching all the children, you can set up a signal handler to handle SIGCHLD ... from perlipc:

  use POSIX ":sys_wait_h"; $SIG{CHLD} = sub { while ((my $child = waitpid(-1, WNOHANG)) > 0) { $Kid_Status{$child} = $?; } }; # do something that forks... 
+3
source

The ability to enable and process SIGCHLD is also possible; it will notify you of changes in the state of the child process without polling - see sigprocmask (2) and signal (3) on the manual pages.

+1
source

Source: https://habr.com/ru/post/1369645/


All Articles