2009-07-06 50 views
3

在Solaris 9(Sparc)的chroot環境中運行Perl時,我遇到了一些奇怪的錯誤。我們使用自定義Perl,但它幾乎完全是Perl 5.8.7,這個版本已經在包括Solaris 8-10在內的各種平臺上運行了多年。在Solaris上睡覺時遇到SIGALRM 9

下面的代碼是非常簡單的:

#!/usr/bin/perl 
use strict; 
use warnings; 

print "About to sleep(1)\n"; 
sleep 1; 
print "Just woke up!\n"; 

但是,如果我運行, 「剛睡醒!」永遠不會被打印 - 相反,程序結束並且「鬧鐘」被回顯到屏幕上。這隻有在睡眠時纔會發生 - 如果我編寫的程序執行很多數學運算並需要10秒鐘才能運行,則一切正常。它也只發生在chroot環境中。

我已經轉儲了%SIG,其中有一個'ALRM => undef'的條目,這是預期的 - 非chrooted環境具有相同的行爲。但是,如果我將腳本更改爲包括:

$SIG{ALRM} = sub {}; 

...一切正常。那麼,交易是什麼?我沒有太多的Solaris經驗,但必須有一種方法可以使默認的信號處理程序正常工作。

回答

3

我想嘗試的第一件事就是到下桁架運行示例程序:

truss testprogram.pl 

這將顯示用於實現睡眠實際的系統調用。在我有訪問Solaris 8系統,輸出的相關部分是:

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 

在Solaris 10主機,它輸出:

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 

我想你會得到更接近於到Solaris 8的輸出,它可能會出於某種原因顯示sigaction()調用失敗。

除此之外,我會檢查chroot/usr/lib中的共享庫實際上是主機和操作系統版本的正確版本。桁架輸出還將顯示perl正在加載哪些共享庫。

9

我建議簡單地用select(undef, undef, undef, 1)替換sleep 1調用並避免整個問題。

從你給出的症狀來看,我打賭你的chroot'd perl腳本正在實現sleep(根據POSIX的許可),並且由於某些原因,perl沒有捕獲那個信號,因爲它應該,也許是因爲它沒有期待實施。它是你自定義的Perl構建?這是chroot'd libc中的特質嗎? chroot下的perl -e "sleep 1"是否顯示相同的問題?等等很難說沒有訪問的環境和工具,如桁架

同樣,整個問題都可以避免:select不會與SIGALRM混淆。

+1

不幸的是,我不能這樣做 - 我正在處理在多個平臺上運行的非常大的代碼庫。我沒有改變它只爲Solaris 9 :) 你提到的POSIX標準很可能是這種情況。我很確定我的perl構建不會混亂,但它可能是chroot的libc版本。謝謝:) – 2009-07-06 04:26:03

+1

AFAICT,`select()`可以在所有平臺上工作... – Massa 2009-07-06 10:36:21

1

您是否還有Solaris附帶的Perl版本?如果是這樣,那就試試你的代碼吧。如果你沒有這個版本,那麼我建議你下載Perl 5.8.7,編譯一個股票版本,然後測試你的腳本。

如果您的腳本在這兩個版本中的任意一個上運行正確,那麼您知道問題與您的Perl版本中的更改有關。如果腳本具有相同的錯誤,那麼我會建議下載Perl 5.8.9,編譯它,然後檢查錯誤是否消失。如果沒有,那麼恭喜你,你在Perl中發現了一個錯誤。您可能需要運行perlbug來報告它。