Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Problemi con Time::Hires

17 views
Skip to first unread message

Matteo

unread,
Feb 9, 2012, 10:46:33 AM2/9/12
to
Salve,
ho un programma A che ad intervalli regolari esegue una funzione e che ad
un cero punto avvia un altro programma B che esegue altre funzioni ad
intervalli regolari.

Se avvio i programmi da due terminali diversi questi funzionano
correttamente, ma se faccio avviare il programma B dal programma A
succede che il programma A continua a funzionare mentre nel programma B
non funzionano più i timer.

Ecco un esempio minimale: salvate il codice seguente con nome progA.pl e
progB.pl e provate ad eseguire progA.pl

#!/usr/bin/perl
use warnings;
use strict;
use Time::HiRes qw ( setitimer ITIMER_REAL );
$SIG{ALRM} = sub{&alarm};
setitimer(ITIMER_REAL,1,1);
my $i=0;
my $t=<>;
exit 0;

sub alarm{
$i++;
system('perl progB.pl&') if($i==3);
print STDERR "$i\n";
}


Come output mi aspetterei di vedere qualcosa tipo
1
2
3
1
4
2
5
3
Invece il programma B parte ma non chiama la sub alarm.
Se si avviano i due programmi da due terminali si nota che i timer di
entrambi i programmi funzionano.
Dove sbaglio?

Grazie,
Matteo

Emanuele Zeppieri

unread,
Feb 11, 2012, 10:47:58 AM2/11/12
to
On Feb 9, 4:46 pm, Matteo <fakem...@fakehost.fakedomain> wrote:

> [...]
> Invece il programma B parte ma non chiama la sub alarm.

È POSIX che vuole così, né Perl né tanto meno Time::HiRes (difatti
avresti la stessa situazione anche con una semplice alarm()).

La situazione (un po' intricata, ma neanche tanto) è la seguente.

All'interno del signal handler, il recapito del segnale stesso (nel
tuo caso SIGALRM) viene bloccato, mediante la cosiddetta /process
signal mask/, la quale signal mask (del processo padre) viene
ereditata da un eventuale processo forkato.

Ora la system di Perl esegue come prima cosa una fork, e siccome tu
esegui la system dentro un signal handler, dove come detto la signal
mask blocca il segnale SIGALRM, tale signal mask viene passata pari
pari al processo invocato via system, che pertanto a sua volta
ignorerà ogni SIGALRM che gli dovesse eventualmente pervenire.

Per far funzionare le cose come vuoi tu, dovresti resettare la signal
mask nel processo figlio, cosa che puoi fare semplicemente aggiungendo
queste due righe all'inizio di progB.pl:

use POSIX qw(:signal_h);
sigprocmask( SIG_UNBLOCK, POSIX::SigSet->new(SIGALRM) );

Ciao
-Emanuele

Matteo

unread,
Feb 13, 2012, 5:40:29 AM2/13/12
to
Grazie mille, da solo non ce l'avrei mai fatta!
(certe cose sono difficili da chiedere a google)

Emanuele Zeppieri

unread,
Feb 13, 2012, 12:59:43 PM2/13/12
to
On Feb 13, 11:40 am, Matteo <fakem...@fakehost.fakedomain> wrote:

> Grazie mille, da solo non ce l'avrei mai fatta!
> (certe cose sono difficili da chiedere a google)

Di nulla figurati.
E grazie al fatto che hai condiviso il problema, in futuro sarà più
facile trovarlo su Google.
0 new messages