2012-08-23 4 views
3
#!/usr/bin/perl 

use POSIX ":sys_wait_h"; 
$SIG{CHLD} = \&REAPER; 

sub REAPER { 
    my $pid; 
    while (($pid = waitpid(-1, WNOHANG)) > 0) { 
     print "where is here,$pid\n"; 
    } 
} 

sub child { 
    print "I'm child, pid=$$.\n"; 
    sleep 2; 
} 

$lid = fork(); 
if ($lid == 0) { 
    &child; 
    exit; 
} else { 
    sleep 1000; 
    print "I am parent, child pid : $lid\n"; 
} 

Sortie:sommeil Perl terminé par SIGCHLD

I'm child, pid=11839. 
where is here,11839 
I am parent, child pid : 11839 

Ce qui précède est mon script Perl. La sortie est bonne, mais une chose étrange est qu'il imprime I am parent, child pid : 11839 immédiatement après la dernière sortie. Pourquoi le sleep 1000 n'a-t-il aucun effet?

Répondre

2

S'il vous plaît toujoursuse strict et use warnings, et déclarer vos symboles en utilisant my à leur point de définition. Cela est particulièrement vrai lorsque vous demandez de l'aide, car ces mesures peuvent révéler des bugs simples qui sont par ailleurs facilement passer inaperçue

sleep est mis en œuvre à l'aide setitimer pour demander un SIGALRM après un intervalle spécifié, puis pause de suspendre le processus jusqu'à ce qu'il reçoit le signal. Mais si un SIGCHLD vient en premier, le processus sera également réactivé.

Le masque de signal ne peut pas être réglé pour éviter cela sinon la SIGCHLD n'obtiendraient viabilisé

+0

Ce n'est pas ainsi que 'sleep' est implémenté, dans la plupart des OS/Perls de cette décennie, ou dans le noyau. Voir https://linux.die.net/man/3/usleep –

+0

@ZacB: Je regarde la source C de Perl v5.24 et votre commentaire semble injuste. S'il vous plaît ajouter une réponse qui définit correctement comment un appel Perl 'sommeil' fonctionne dans vos yeux. Notez qu'il n'appelle pas 'usleep' que vous avez lié. – Borodin

+1

@ZacB Alors, comment est-il mis en œuvre? Je voudrais savoir, si ce n'est pas comme ça. Le lien que vous fournissez est juste la page de manuel de 'usleep', ce qui ne me dit rien sur la façon dont Perl implémente le sien. La page de Perl pour [sleep] (http://perldoc.perl.org/functions/sleep.html) fait en fait allusion à 'setitimer'. Notez que 'usleep' _à partir d'un module_ qui est mentionné ne semble pas utiliser _ syscall (voir les documents du module). Pouvez-vous fournir des documents ou des pointeurs? – zdim

8

Ceci est documented: « Peut être interrompu si le processus reçoit un signal ». Le but est de permettre aux gestionnaires de signaux de fonctionner. Il suffit de se rendormir si ce n'est pas le moment de se réveiller.

use Time::HiRes qw(time sleep); # Optional. 

sub unint_sleep($) { 
    my $sleep_til = time + $_[0]; 
    for (;;) { 
     my $sleep_dur = time - $sleep_til; 
     last if $sleep_dur <= 0; 
     sleep($sleep_dur); 
    } 
}