如何在perl模块中正确分叉znc?

时间:2010-05-13 19:06:13

标签: perl fork irc

我正在写一个IRC机器人。脚本作为ZNC中的perl模块加载,但如果我创建分叉进程,则bot会因输入/输出错误而断开连接。这是一个没有fork的工作示例脚本,但这会导致僵尸程序冻结,直到脚本完成其任务。

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不应该放在子进程中。

2 个答案:

答案 0 :(得分:2)

fork()调用对打开的文件和套接字句柄有影响,包括:

  

文件描述符(有时会锁定     这些描述符是共享的,而其他一切都被复制了。

     

...

     

从v5.6.0开始,Perl将尝试刷新所有文件   在分叉子进程之前打开输出,但是这个   某些平台可能不支持(请参阅perlport)。成为   安全,你可能需要设置$ | ($ AUTOFLUSH英文)或致电   在任何打开的句柄上的“IO :: Handle”的“autoflush()”方法   以避免重复输出。

一般来说,在一个进程中设置套接字连接并尝试在子进程中读取/写入该连接并不是一个好主意。

解决方法可能是在子进程中创建新的ZNC连接(在a_slow_process()完成后),编写您的私人消息,然后关闭新连接。

答案 1 :(得分:0)

如果你不喜欢用c ++重写你的模块,znc有一个CExecSock,它包装popen2()并且应该做你需要的。您可以查看shell.cpp模块中的示例用法。