开发者

How do I fork correctly in a perl module for znc?

开发者 https://www.devze.com 2022-12-30 18:59 出处:网络
I\'m currently writing an IRC bot. The scripts are loaded as perl modules in ZNC but the bot gets disconnected with an Input/Output error if I create a forked process. This is a working example script

I'm currently writing an IRC bot. The scripts are loaded as perl modules in ZNC but the bot gets disconnected with an Input/Output error if I create a forked process. This is a working example script without f开发者_高级运维ork, but this causes the bot to freeze until the script finishes doing its task.

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;

The fork code that is causing the error is commented out. How do I fix this?

Edited to add: I was told that ZNC::PutIRC should not be put in the child process.


A fork() call has effects on open file and socket handles, including:

File descriptors (and sometimes locks on those descriptors) are shared, while everything else is copied.

...

Beginning with v5.6.0, Perl will attempt to flush all files opened for output before forking the child process, but this may not be supported on some platforms (see perlport). To be safe, you may need to set $| ($AUTOFLUSH in English) or call the "autoflush()" method of "IO::Handle" on any open handles in order to avoid duplicate output.

and in general it is not a good idea to set up a socket connection in one process and try to read/write on that connection in a child process.

A workaround might be to make a new ZNC connection in the child process (after a_slow_process() is done), write your private message, and then close the new connection.


If you're not adverse to rewriting your module in c++, znc has a CExecSock which wraps popen2() and should do what you need. You can look in the shell.cpp module for example usage.

0

精彩评论

暂无评论...
验证码 换一张
取 消