Xpoint
   [напомнить пароль]

fork() и STDIN ссорятся, в чем может быть проблема?

Метки: [без меток]
[удл]
2006-10-11 23:23:19 [обр] Bohdan[досье]
This is perl, v5.8.7 built for MSWin32-x86-multi-thread
(Windows XP)

Есть такой себе модуль Net::OSCAR:
"Net::OSCAR - Implementation of AOL's OSCAR protocol for instant messaging (for interacting with AIM a.k.a. AOL IM a.k.a. AOL Instant Messenger - and ICQ, too)"
Склепал я по примеру в мануале скриптик, который исправно работает, получает сообщения, проверяет по регекспу, и овтечает, НО!
Захотелось мне прикрутить к нему возможность "человеческого" ответа. Поскольку другого способа кроме как через STDIN я не знаю (ну можно конечно писать в паралельный файл, из него читать на таймауте аналогично tail'у, и отсылать, но этот вариант мне не нравится), то решил повесить это дело на fork(); (я знаю что fork() под Виндой работает не слишком хорошо, но тем не менее), и получилось то что получилось:

use Net::OSCAR qw(:standard);
use Locale::Recode;

my $cd;
$cd = Locale::Recode->new (from => 'CP1251', to => 'IBM866');
die $cd->getError if $cd->getError;

my ($login_uin, $login_pass) = ($ARGV[0], $ARGV[1]);

sub im_in {
   my($oscar, $sender, $message, $is_away) = @_;

   if ($message =~ /1/)
   {
      print "got one!\n";
      $oscar->send_im($sender, "got one!");
   }
   elsif ($message eq 'quit')
   {
      $oscar->send_im($sender, "bye.");
      $oscar->signoff();
      waitpid($pid,0);
      exit();
   }
   else { $oscar->send_im($sender, $message); }

   print "[AWAY] " if $is_away;
   $cd->recode($message) or die $cd->getError;
   print "$sender: $message\n";
}

$oscar = Net::OSCAR->new();
$oscar->set_callback_im_in(\&im_in);
$oscar->signon($login_uin, $login_pass);

my $pid = fork();

if (not defined $pid) {
   print "resources not avilable.\n";
} elsif ($pid == 0) {
   print "Child spawned.\n";
   while(<STDIN>)
   {
      chomp;
      $message = $_;
      if ($message eq 'quit')
      {
         $oscar->signoff();
         waitpid($pid,0);
         exit()
      }
      $oscar->send_im($sender, $message) or die $!;
      print "sent> ".$_."\n";
   }
} else {
   print "Parent spawned.\n";
   while(1) {
      $oscar->do_one_loop();
   }
}
waitpid($pid,0);
exit();

Поскольку fork использую впервые, да и с ООП не слишком дружу, то чувствую что ошибка елементарна. Но тем не менее, где она лежит, понять не могу.
Собсно, вопросы:

  1. Как лучше читать STDIN в форке, из child'а или из parent'а?
  2. Какого чёрта клонированный объект, работающий на while под parent'ом не хочет реагировать на запросы под child'ом ? при чем под parent'ом он тоже не хочет реагировать.

PS. При вводе текста умирает с ошибкой "Bad file descriptor at C:\test.pl line 52, <STDIN> line 1."

PPS. Ставил fork() на 31-ю строчку, та же ошибка.

Powered by POEM™ Engine Copyright © 2002-2005