SIGALRM mentre dorme su Solaris 9
Domanda
Sto riscontrando un errore un po' strano mentre eseguo Perl in un ambiente chroot su Solaris 9 (Sparc).Noi Sono utilizzando un Perl personalizzato, ma è quasi esattamente Perl 5.8.7 e questa versione è in esecuzione da anni su varie piattaforme incluso Solaris 8-10.
Il codice seguente è piuttosto semplice:
#!/usr/bin/perl
use strict;
use warnings;
print "About to sleep(1)\n";
sleep 1;
print "Just woke up!\n";
Tuttavia, se eseguo questo, "Mi sono appena svegliato!" non viene mai stampato - invece, il programma termina e "Sveglia" viene riecheggiato sullo schermo.Questo succede solo se c'è una pausa: se scrivo un programma che fa molti calcoli e impiega 10 secondi per essere eseguito, tutto funziona bene.Succede anche solo in un ambiente chroot.
Ho scaricato %SIG, che ha una voce 'ALRM => undef', come previsto: l'ambiente non chroot ha lo stesso comportamento.Tuttavia, se cambio lo script per includere:
$SIG{ALRM} = sub {};
...tutto funziona bene.Allora, qual è il problema?Non ho molta esperienza con Solaris, ma deve esserci un modo per far sì che i gestori di segnale predefiniti si comportino correttamente.
Soluzione
La prima cosa che mi piacerebbe provare è quello di eseguire il programma di esempio sotto capriata:
truss testprogram.pl
Questo mostrerà le chiamate di sistema effettivi utilizzati per implementare il sonno. Su un sistema Solaris 8 che ho accesso, la parte rilevante della produzione è:
write(1, " A b o u t t o s l e".., 18) = 18
time() = 1247258429
alarm(0) = 0
sigaction(SIGALRM, 0xFFBEF6E0, 0xFFBEF790) = 0
sigfillset(0xFF0C28D0) = 0
sigprocmask(SIG_BLOCK, 0xFFBEF780, 0xFFBEF770) = 0
alarm(1) = 0
Received signal #14, SIGALRM, in sigsuspend() [caught]
sigsuspend(0xFFBEF760) Err#4 EINTR
setcontext(0xFFBEF448)
alarm(0) = 0
sigprocmask(SIG_UNBLOCK, 0xFFBEF780, 0x00000000) = 0
sigaction(SIGALRM, 0xFFBEF6E0, 0x00000000) = 0
time() = 1247258430
Just woke up!
write(1, " J u s t w o k e u p".., 14) = 14
In un host Solaris 10, essa stampa:
write(1, " A b o u t t o s l e".., 18) = 18
time() = 1247258270
nanosleep(0xFFBFF770, 0xFFBFF768) = 0
time() = 1247258271
Just woke up!
write(1, " J u s t w o k e u p".., 14) = 14
Immagino si otterrà qualcosa di più vicino all'uscita Solaris 8, ed è probabilmente mostro il sigaction () chiamata per un motivo qualsiasi.
Al di là di questo, mi piacerebbe verificare che le librerie condivise all'interno del chroot / usr / lib sono in realtà le versioni corrette per l'host e la versione del sistema operativo. L'uscita capriata mostrerà anche esattamente quali hanno condiviso le librerie vengono caricati da perl.
Altri suggerimenti
Consiglio semplicemente di sostituire il sleep 1
chiama con select(undef, undef, undef, 1)
ed evitare l'intera questione.
Dai sintomi che fornisci, scommetto che il tuo script Perl chroot è in fase di implementazione sleep
in termini di SIGALRM
(come consentito da POSIX), e che per qualche ragione perl non cattura il segnale come dovrebbe, forse perché non si aspetta tale implementazione.È la tua build personalizzata di Perl?È un'idiosincrasia nel chroot'd libc
?Fa perl -e "sleep 1"
sotto chroot mostra lo stesso problema?Eccetera.Eccetera.Difficile dirlo senza l'accesso all'ambiente e uno strumento simile capriata.
Ancora una volta, l’intero problema può essere evitato: select
non giocherà con SIGALRM
.
Hai ancora la versione di Perl che viene fornito con Solaris? Se è così, allora provare il codice su di esso. Se non si dispone di quella versione, allora vi consiglio di scaricare Perl 5.8.7 , la compilazione di una versione magazzino, e quindi testare lo script su di esso.
Se lo script viene eseguito correttamente, in una di queste due versioni, poi si sa il problema è legato ai cambiamenti nella vostra versione di Perl. Se lo script ha lo stesso errore, quindi poi vorrei suggerire il download di Perl 5.8.9 , compilarlo, e quindi il controllo per vedere se il bug va via. Se non lo fa, allora, complimenti, avete trovato un bug in Perl. Probabilmente si desidera eseguire perlbug di segnalarlo.