Process supervision and exception

Discussion in 'Perl Misc' started by titetluc@gmail.com, May 11, 2007.

  1. Guest

    Hi all

    My problem: I have a library managing Perl objects
    An object may be composed of several processes

    Here is an example of my library (be careful: the sleep call are used
    only for debug purpose !!)
    #!/usr/bin/perl -w
    use strict;

    package obj;

    sub new
    {
    my $class = shift;
    my %param = @_;
    my %obj;
    $obj{name} = $param{name};

    my @pid;
    $pid[0] = fork();
    if (!$pid[0]){
    sleep(5);
    # the treatment to be declared here
    exit(1);
    }
    print "PID: $pid[0]";
    $pid[1] = fork();
    if (!$pid[1]){
    sleep(10000);
    # the treatment to be declared here
    }
    print "PID: $pid[1]";

    bless \%obj, $class;
    }

    sub action
    {
    my $obj = shift;
    sleep(10000);
    }

    __END__

    I would like my library to raise an exception when one of the process
    dies for any reasons.

    A code, implementing the process death detection and the exception
    raise, could be:

    sub watch
    {
    my @pid = @_;
    my $p = waitpid(-1,0);
    my $to_kill = $pid[0];
    if ($p == $to_kill){
    $to_kill = $pid[1];
    }
    kill 15, $to_kill;
    die "goodbye cruel world\n";
    }


    I could then use the library as follows:

    package main;
    sub main
    {
    my $o1 = obj->new(name=> 'o1');
    my $o2 = obj->new(name=> 'o2');

    eval {$o1->action();};
    if ($@){
    print "o1 killed\n";
    }
    eval {$o2->action();};
    if ($@){
    print "o2 killed\n";
    }
    }

    main();
    1;

    My problem is that I don't know how to call the 'watch' function

    .. I could call it in a CHLD sig handler, but in this case I do not
    know which object "generates" the CHLD signal. In addtion, the method
    is very intrusive because it requires the signal handler declaration
    in the main module.
    .. I could declare a thread supervision per object (adding the line
    threads->new(\&watch, @pid)->detach(); in the obj::new constructor)
    but this does not run (message 'thread failed to start: goodbye cruel
    world')

    I didn't find any information in this group nor in perldoc
    Any idea ?

    Thanks

    Gaetan
    , May 11, 2007
    #1
    1. Advertising

  2. Guest

    wrote:
    > Hi all
    >
    > My problem: I have a library managing Perl objects
    > An object may be composed of several processes
    >
    > Here is an example of my library (be careful: the sleep call are used
    > only for debug purpose !!)



    The above doesn't really describe what it is you want to do. And your code
    also doesn't do what you want it to do. Between the two of those, I'm left
    wondering just what it is you want to do.



    > #!/usr/bin/perl -w
    > use strict;
    >
    > package obj;
    >
    > sub new
    > {
    > my $class = shift;
    > my %param = @_;
    > my %obj;
    > $obj{name} = $param{name};
    >
    > my @pid;
    > $pid[0] = fork();
    > if (!$pid[0]){
    > sleep(5);
    > # the treatment to be declared here
    > exit(1);
    > }
    > print "PID: $pid[0]";
    > $pid[1] = fork();
    > if (!$pid[1]){
    > sleep(10000);
    > # the treatment to be declared here
    > }
    > print "PID: $pid[1]";
    >
    > bless \%obj, $class;
    > }


    @pid is lexical to the sub new, and isn't saved anywhere, so once new
    finishes, @pid is lost.

    >
    > sub action
    > {
    > my $obj = shift;
    > sleep(10000);
    > }
    >
    > __END__
    >
    > I would like my library to raise an exception when one of the process
    > dies for any reasons.
    >
    > A code, implementing the process death detection and the exception
    > raise, could be:
    >
    > sub watch
    > {
    > my @pid = @_;
    > my $p = waitpid(-1,0);
    > my $to_kill = $pid[0];
    > if ($p == $to_kill){
    > $to_kill = $pid[1];
    > }
    > kill 15, $to_kill;
    > die "goodbye cruel world\n";
    > }


    What if the thing waitpid returns is neither $pid[0] or $pid[1]?


    > I could then use the library as follows:
    >
    > package main;
    > sub main
    > {
    > my $o1 = obj->new(name=> 'o1');
    > my $o2 = obj->new(name=> 'o2');
    >
    > eval {$o1->action();};
    > if ($@){
    > print "o1 killed\n";
    > }


    What if one of the processes from $o2 dies while in the middle of
    $o1->action? What is the desired action?

    > eval {$o2->action();};
    > if ($@){
    > print "o2 killed\n";
    > }
    > }
    >
    > main();
    > 1;
    >
    > My problem is that I don't know how to call the 'watch' function


    I don't think that there is any right way to call your existing watch
    function. You need to re-arrange it.

    >
    > . I could call it in a CHLD sig handler, but in this case I do not
    > know which object "generates" the CHLD signal.


    You need a global (or widely-scoped lexical) hash that records the pids
    that are started as keys, and the object that started it (or maybe some
    kind of closure) as values. Then in a subroutine which is triggered by
    SIGCHLD (or some other way), you would call waitpid, get the return value,
    and look it up in the global hash to see what object you are in.


    my $kid;
    while (($kid = waitpid(-1, WNOHANG)) >0) {
    die "Someone is spawning children ($kid) without telling me!"
    unless exists $global_pid{$kid};
    my $object = delete $global_pid{$kid};
    if ($object->action_pending()) {
    # action is pending on this action, so die to get out of it
    die "Something went wrong with the object you are trying to use"
    } else {
    # no object pending, don't die until next time this object is used.
    $object->hosed(1);
    };
    };


    > In addtion, the method
    > is very intrusive because it requires the signal handler declaration
    > in the main module.


    Not all situations can be handled in a nice encapsulated manner. For Perl,
    at least, this is one of those situations. I don't think you will find any
    non-intrusive way to do this.


    > . I could declare a thread supervision per object (adding the line
    > threads->new(\&watch, @pid)->detach(); in the obj::new constructor)
    > but this does not run (message 'thread failed to start: goodbye cruel
    > world')


    Oh ick. Management of threading and forking are both bad enough on their
    own. Mixing them is just that much worse.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
    , May 11, 2007
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Johnson Sr.

    System.Diagnostic.Process and disfunctional process

    Michael Johnson Sr., Feb 17, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    1,953
    Michael Johnson Sr.
    Feb 17, 2004
  2. Michael Johnson Sr.

    System.Diagnostic.Process and disfunctional process.

    Michael Johnson Sr., Feb 17, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    318
    Michael Johnson Sr.
    Feb 17, 2004
  3. Elaine Cheong
    Replies:
    1
    Views:
    1,006
    Gordon Beaton
    Dec 9, 2006
  4. Replies:
    2
    Views:
    334
  5. George2
    Replies:
    15
    Views:
    891
    Alf P. Steinbach
    Jan 29, 2008
Loading...

Share This Page