2

我目前正在编写一个 IRC 机器人。脚本在ZNC中作为 perl 模块加载,但如果我创建分叉进程,机器人会因输入/输出错误而断开连接。这是一个没有 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;

导致错误的分叉代码被注释掉。我该如何解决?

编辑添加:有人告诉我 ZNC::PutIRC 不应该放在子进程中。

4

2 回答 2

2

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

文件描述符(有时是这些描述符上的锁)是共享的,而其他所有内容都被复制。

...

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

通常,在一个进程中建立套接字连接并尝试在子进程中对该连接进行读/写并不是一个好主意。

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

于 2010-05-14T01:48:49.353 回答
0

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

于 2010-11-17T17:58:43.783 回答