Papo Napolitano wrote:

>> On Feb 18, 2004, at 4:45 PM, Papo Napolitano wrote:
>> 
>> > Heh, sorry... I simplified the code...
>> > I'm still not posting the full source because it's like 15 files :(
>> >
>> >
>> > while (1) {
>> >   Fork("Whatever");
>> >   sleep 60;
>> > }
>> 
>> The first time you showed this loop, it had multiple fork()s in it.
>> Now it's just one.  Which is it.
>> 
>> > sub Fork {
>> >   my $module = shift;
>> >   my @params = @_;
>> >   my $pid = fork;
>> >   return $pid if $pid;
>> >   $module->Run(@params);
>> >   exit;
>> > }
>> 

[snip]

> 
> I'm changing the code to try to make it work... Right now I'm using:
> 
> for ('test1', 'test2', 'test3') {
>   print STDERR scalar(localtime) . " - fork $_\n";
>   Fork("TestModule", $_);
>   print STDERR scalar(localtime) . " - enter sleep\n";
>   sleep 60;
>   print STDERR scalar(localtime) . " - exit sleep\n";
> }
> 
> And in TestModule.pm:
> 
> package TestModule;
> sub Run {
>   my $self = shift;
>   my $param = shift;
>   print STDERR scalar(localtime) . " - $self: $param\n";
> }
> 
> Output is this:
> 
> Wed Feb 18 20:37:04 2004 - fork test1
> Wed Feb 18 20:37:04 2004 - enter sleep
> Wed Feb 18 20:37:04 2004 - TestModule: test1
> Wed Feb 18 20:37:04 2004 - exit sleep
> Wed Feb 18 20:37:04 2004 - fork test2
> Wed Feb 18 20:37:04 2004 - enter sleep
> Wed Feb 18 20:37:04 2004 - TestModule: test2
> Wed Feb 18 20:37:04 2004 - exit sleep
> Wed Feb 18 20:37:04 2004 - fork test3
> Wed Feb 18 20:37:04 2004 - enter sleep
> Wed Feb 18 20:37:04 2004 - TestModule: test3
> Wed Feb 18 20:37:04 2004 - exit sleep
> Wed Feb 18 20:37:04 2004 - fork test1
> Wed Feb 18 20:37:04 2004 - enter sleep
> Wed Feb 18 20:37:04 2004 - TestModule: test1
> Wed Feb 18 20:37:04 2004 - exit sleep
> Wed Feb 18 20:37:04 2004 - fork test2
> Wed Feb 18 20:37:04 2004 - enter sleep
> Wed Feb 18 20:37:04 2004 - TestModule: test2
> Wed Feb 18 20:37:04 2004 - exit sleep
> Wed Feb 18 20:37:04 2004 - fork test3
> Wed Feb 18 20:37:04 2004 - enter sleep
> Wed Feb 18 20:37:04 2004 - TestModule: test3
> Wed Feb 18 20:37:04 2004 - exit sleep

sleep is interruptable (ie, signals can wake it up) and that's why it's 
popular for busy wait in a loop. the following demonstrates this side 
affect:

#!/usr/bin/perl -w
use strict;

my $stop = 0;

$SIG{CHLD} = sub{wait; $stop = 1};

my $p = fork;

if($p){
        while(!$stop){
                print 5 - sleep(5)," seconds left to be sleep ($$)\n";
        }
}else{
        sleep(14);
        exit;
}

__END__

prints:

0 seconds left to be sleep (7632)
0 seconds left to be sleep (7632)
1 seconds left to be sleep (7632)

the first line means the parent slept 5 full seconds
the second line also means the parent slept 5 full seconds
the third line shows the parent only slept 4 (5-4=1) seconds

do a little math gives us: 5 + 5 + 4 = 14 which is exactly the time
the child finished and wake up the parent. 

there is no general solution to stop sleep from wake up by a signal although 
most *nix os support something called an uninterrupted sleep which a system 
call is make to put the process to sleep and only another special system 
call can wake it up. you need to code this in C so i will not show you the 
example in this Perl list.

having said that, there is a not so perfect solution which simply cache 
whatever sleep return and sleep more. for example, the following makes sure 
you sleep at least full 7 seconds:

#!/usr/bin/perl -w
use strict;

$SIG{CHLD} = sub{wait};

if(fork){
        print scalar localtime,"\n";
        real_sleep(7);
        print scalar localtime,"\n";
}else{
        sleep(3);
        exit;
}

sub real_sleep{
        my $s = shift;
        my $t = 0;
        while(1){
                my $i = sleep($s);
                unless($i){
                        return;
                }else{
                        $s -= $i;
                }
                print "$s more seconds to sleep\n";
        }
}

__END__

prints:

Thu Feb 19 10:36:45 2004
4 more seconds to sleep
0 more seconds to sleep
Thu Feb 19 10:36:52 2004

the second line is caused by the exiting of the child process which died 
after 3 seconds (4 + 3 = 7). unlike the previous version the child did not 
affect our parent process and we slept full 7 seconds. this work even you 
have multiple children. you probably need to do something similiar in your 
script to make sure you sleep enough seconds.

as a final note, the above code is "correct" only in terms of algr. and how 
the sleep function is suppose to work. external factors such as machine 
load, cpu demands, etc can cause the machine to be not able to wake up at 
the precise moment so you must account for that. 

david
-- 
sub'_{print"@_ ";* \ = * __ ,\ & \}
sub'__{print"@_ ";* \ = * ___ ,\ & \}
sub'___{print"@_ ";* \ = * ____ ,\ & \}
sub'____{print"@_,\n"}&{_+Just}(another)->(Perl)->(Hacker)

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to