Как правильно разветвляться в модуле perl для znc? - PullRequest
2 голосов
/ 13 мая 2010

Я сейчас пишу бот IRC. Скрипты загружаются как модули perl в ZNC , но бот отключается с ошибкой ввода / вывода, если я создаю разветвленный процесс. Это рабочий пример сценария без разветвления, но он заставляет бота зависать до тех пор, пока сценарий не выполнит свою задачу.

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 не следует помещать в дочерний процесс.

Ответы [ 2 ]

2 голосов
/ 14 мая 2010
Вызов

A fork() влияет на дескрипторы открытого файла и сокета, в том числе:

Файловые дескрипторы (а иногда и блокировки эти дескрипторы) являются общими, а все остальное копируется.

...

Начиная с v5.6.0, Perl попытается сбросить все файлы открыт для вывода перед разветвлением дочернего процесса, но это может не поддерживаться на некоторых платформах (см. perlport). Быть безопасно, вам может понадобиться установить $ | ($ AUTOFLUSH на английском языке) или позвоните метод autoflush () для IO :: Handle на любых открытых дескрипторах в Чтобы избежать дублирования вывода.

и вообще не рекомендуется устанавливать соединение с сокетом в одном процессе и пытаться читать / записывать это соединение в дочернем процессе.

Обходной путь может заключаться в создании нового ZNC-соединения в дочернем процессе (после выполнения a_slow_process()), написании личного сообщения и закрытии нового соединения.

0 голосов
/ 17 ноября 2010

Если вы не против того, чтобы переписать свой модуль на c ++, у znc есть CExecSock, который оборачивает popen2 () и должен делать то, что вам нужно. Вы можете посмотреть в модуле shell.cpp пример использования.

...