Tuesday, February 17, 2015

Writing signal-aware waitpid in Perl

As I have talked in YAPC::Asia couple of years ago, the wait functions (e.g. wait, waitpid) of Perl do not return EINTR when receiving a signal.

This is a problem if you would want to wait for child processes until receiving a signal. Proc::Wait3 can be a solution, however the module may be hard to install as it is an XS module. It should also be noted that the module provides replacement for wait only; no workaround exists for waitpid.

So today I have scrubbed my head wondering if I could come up with a pure-perl solution, and, here it is. The Perl script below launches a worker process (that just sleeps), and waits for the process to complete, or until SIGTERM is being received.

use strict;
use warnings;
use Errno ();

our $got_sigterm = 0;
our $sighandler_should_die = 0;

# fork a child process that does the task
my $child_pid = fork;
die "fork failed:$!"
    unless defined $child_pid;
if ($child_pid == 0) {
    # in child process, do something...
    sleep 100;
    exit 0;
}

$SIG{TERM} = sub {
    $got_sigterm = 1;
    die "dying to exit from waitpid"
        if $sighandler_should_die;
};

warn "master process:$$, child process:$child_pid";

# parent process, wait for child exit or SIGTERM
while (! $got_sigterm) {
    if (my_waitpid($child_pid, 0) == $child_pid) {
        # exit the loop if child died
        warn "child process exitted";
        $child_pid = -1;
        last;
    }
}

if ($child_pid != -1) {
    warn "got SIGTERM, stopping the child";
    kill 'TERM', $child_pid;
    while (waitpid($child_pid, 0) != $child_pid) {
    }
}

sub my_waitpid {
    my @args = @_;
    local $@;
    my $ret = eval {
        local $sighandler_should_die = 1;
        die "exit from eval"
            if $got_sigterm;
        waitpid($args[0], $args[1]);
    };
    if ($@) {
        $ret = -1;
        $! = Errno::EINTR;
    }
    return $ret;
} 

The trick is that waitpid is surrounded by a eval within the my_waitpid function, and the signal handler calls die to exit the eval if the $sighandler_should_die flag is being set. It is also essential to check the $got_sigterm flag within the eval block after setting the $sighandler_should_die flag, since otherwise there would be a race condition.

By using these tricks it has now become possible to implement process managers in pure-perl!

20 comments:


  1. افضل شركة نقل عفش بجدة شركة الاطلال شركة نقل اثاث بجدة شركة متخصصة فى نقل اثاث بجدة على اعلى مستوى من نقل العفش بجدة
    شركة نقل عفش بجدة

    ReplyDelete

  2. شركة نقل عفش
    اهم شركات مكافحة حشرات بالخبر كذلك معرض اهم شركة مكافحة حشرات بالدمام والخبر والجبيل والخبر والاحساء والقطيف كذلك شركة رش حشرات بالدمام ومكافحة الحشرات بالخبر
    شركة مكافحة حشرات بالدمام
    شركة تنظيف خزانات بجدة الجوهرة من افضل شركات تنظيف الخزانات بجدة حيث ان تنظيف خزانات بجدة يحتاج الى مهارة فى كيفية غسيل وتنظيف الخزانات الكبيرة والصغيرة بجدة على ايدى متخصصين فى تنظيف الخزانات بجدة
    شركة تنظيف خزانات بجدة
    شركة كشف تسربات المياه بالدمام
    شركة نقل عفش واثاث

    ReplyDelete
  3. Very nice post. I just stumbled up?n your weblog and wished to say that I have really enjoyed browsing ?our blog posts.
    Regards - www.office.com/setup

    ReplyDelete
  4. I can only express a word of thanks. Because with the content on this blog I can add knowledge I, thank has been sharing this information. Do not forget to visit our website to share information and knowledge about health.|
    Cara mengobati Nyeri Belikat |
    Cara Mengatasi Mata Kaki Bengkak |
    obat herbal jantung koroner

    ReplyDelete
  5. I can only express a word of thanks. Because with the content on this blog I can add knowledge I, thank has been sharing this information. Do not forget to visit our website to share information and knowledge about health.|
    Cara Mengobati penyakit kanre pali |
    Obat Filariasis Herbal |

    ReplyDelete
  6. I can only express a word of thanks. Because with the content on this blog I can add knowledge I, thank has been sharing this information. Do not forget to visit our website to share information and knowledge about health. |
    cara mengatasi radang panggul |
    obat infeksi saluran kemih |
    obat herbal infeksi usus |
    sapnudin herbal |
    obat pusing kliyengan |
    nama obat diare pada anak

    ReplyDelete
  7. Subhanallah, this is a very good article. Give me awareness. Because all this time I always had a lot of good intentions, but after I got the things I could share.

    Cara Menghilangkan Nyeri Dan Pegal Di Lutut Cara Mengatasi Emfisema Obat Hipertiroid Cara Mengatasi Tinnitus Obat Amandel Paling Ampuh

    ReplyDelete
  8. Given article is very helpful and very useful for my admin, and pardon me permission to share articles here hopefully helped :

    Obat kesrek tradisional
    Cara menyembuhkan batuk rejan
    Cara Menghilangkan Benjolan Di Kepala

    ReplyDelete
  9. Nice to be visiting your blog again, it has been months for me. Well this article that i’ve been waited for so long. I need this article to complete my assignment in the college, and it has same topic with your article. Thanks, great share :


    cara mengobati kencing manis
    cara mengobati gondok secara alami

    ReplyDelete
  10. What a way to express things. I have found comfort in reading this post and i am sure other users may feel the same, because this post carries a social message in it. Keep it up ! Regards:-
    office.com/setup | norton.com/setup | mcafee.com/activate

    ReplyDelete
  11. norton.com/setup to install setup product key, Learn how to download, install, and put into outfill Norton Setup concerning speaking the subject of your Windows and Mac device.
    http://norton-comnortonnorton.com

    ReplyDelete

Note: Only a member of this blog may post a comment.