我正在写一个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不应该放在子进程中。
答案 0 :(得分:2)
fork()
调用对打开的文件和套接字句柄有影响,包括:
文件描述符(有时会锁定 这些描述符是共享的,而其他一切都被复制了。
...
从v5.6.0开始,Perl将尝试刷新所有文件 在分叉子进程之前打开输出,但是这个 某些平台可能不支持(请参阅perlport)。成为 安全,你可能需要设置$ | ($ AUTOFLUSH英文)或致电 在任何打开的句柄上的“IO :: Handle”的“autoflush()”方法 以避免重复输出。
一般来说,在一个进程中设置套接字连接并尝试在子进程中读取/写入该连接并不是一个好主意。
解决方法可能是在子进程中创建新的ZNC连接(在a_slow_process()
完成后),编写您的私人消息,然后关闭新连接。
答案 1 :(得分:0)
如果你不喜欢用c ++重写你的模块,znc有一个CExecSock,它包装popen2()并且应该做你需要的。您可以查看shell.cpp模块中的示例用法。