2010-05-13 65 views
2

我正在寫一個IRC bot。腳本作爲perl模塊加載到ZNC中,但如果我創建了分叉進程,則bot會與輸入/輸出錯誤斷開連接。這是一個沒有fork的工作示例腳本,但是這會導致殭屍程序凍結,直到腳本完成其任務。如何在zl的perl模塊中正確分叉?

package imdb; 

use warnings; 
use strict; 


sub new 
{ 
my ($class) = @_; 
my $self = {}; 

bless($self, $class); 
return($self); 
} 

sub OnChanMsg 
{ 
my ($self, $nick, $channel,$text) = @_; 

#unless (my $pid = fork()) { 

my $result = a_slow_process($text); 
ZNC::PutIRC("PRIVMSG $channel :$result"); 
# exit; 
#} 

return(ZNC::CONTINUE); 

} 

sub OnShutdown 
{ 
my ($me) = @_; 
} 

sub a_slow_process { 
my $input = shift; 
sleep 10; 
return "You said $input."; 
} 

1; 

導致錯誤的fork代碼被註釋掉。我該如何解決?

編輯添加:有人告訴我ZNC :: PutIRC不應放在子進程中。

+0

什麼是錯誤?這是第一次嘗試還是事後?請注意,每次您致電onchanmsg時,您都會創建一個子進程並刪除原始進程,因此您仍然會在第一次之後從子進程調用PutIRC。你確定你已經考慮過叉子兩條路上發生了什麼嗎? – Kyle 2010-05-13 19:55:40

+0

每次出現「輸入/輸出錯誤」時,bot都會與IRC斷開連接。我不知道如何在沒有將ZNC :: PutIRC放入孩子的情況下進行分岔。我希望它在得到a_slow_process()的結果後將消息發送給IRC。機器人將被凍結,直到它返回ZNC :: CONTINUE,所以我希望一旦孩子分叉就完成了。 – rarbox 2010-05-14 06:23:33

回答

2

一個fork()呼籲對打開的文件和套接字句柄的影響,包括:

文件描述符(有時在 這些描述符鎖)是共享的,而一切被複制。

...

與V5.6.0開始,Perl將嘗試建立該子進程之前刷新打開輸出的所有文件 ,但這 可能無法在某些平臺上(見perlport)的支持。要成爲 安全,您可能需要設置$ | ($ AUTOFLUSH英文)或在 的任何打開的句柄上調用 「IO :: Handle」的「autoflush()」方法以避免重複輸出。

並且通常在一個進程中設置套接字連接並嘗試在子進程中讀寫該連接並不是一個好主意。

解決方法可能是在子進程中創建新的ZNC連接(完成a_slow_process()之後),編寫您的私人消息,然後關閉新的連接。

+0

你能告訴我一個IO :: Handle示例腳本嗎? 新連接在連接後會稍微滯後(特別是如果bot在很多頻道上),這樣就會破壞分叉的目的。 – rarbox 2010-05-14 10:03:53

0

如果你不反對用C++重寫你的模塊,znc有一個包裝popen2()的CExecSock,它應該做你需要的。例如,您可以查看shell.cpp模塊。