POE жалуется, что метод запуска POE::Kernel никогда не вызывался при разветвлении

StackOverflow https://stackoverflow.com/questions/4571307

  •  14-10-2019
  •  | 
  •  

Вопрос

Это мой код:

 if ($DAEMON) {
                my $pid = fork();
                if (not defined $pid) {
                                        print "Unable to start daemon.\n";
                                        exit(1);
                                      }
                elsif ($pid == 0) {
                                   open STDOUT, '>', '/dev/null';
                                   open STDERR, '>', '/dev/null';
                                   _create_sessions($self, $settings);
                                   $poe_kernel->run;
                                  }
                else { print "Script forked to background with PID $pid\n"; }
              }
 else {
        _create_sessions($self, $settings);
        $poe_kernel->run;
      }

Когда $DAEMON = 1, он жалуется, что метод run() POE::Kernel никогда не вызывался, но, как вы можете видеть в приведенном выше коде, я уже это сделал.Сценарий прекрасно работает в режиме демона, но я не могу избавиться от этого предупреждения или понять, почему он так говорит.Я также попробовал вызвать $poe_kernel->has_forked(), но это тоже не помогло.

У меня закончились идеи.Какие-либо предложения?

Обновлено, чтобы добавить:Возможно, я недостаточно ясно выразился.Код ниже создает сеанс и запускает ядро.

_create_sessions($self, $settings);
$poe_kernel->run;

Он работает отлично.Только когда тот же код запускается внутри разветвленного дочернего элемента, чтобы я мог отправить сценарий в фоновый режим, он говорит, что метод запуска POE::Kernel не был вызван.Скрипт переходит в фоновый режим и работает так, как должен, а это означает, что ядро ​​действительно работает.Я всего лишь хочу избавиться от этого надоедливого предупреждения.

Это было полезно?

Решение

Да, это правильно.Предупреждение появляется, потому что экземпляры POE::Session созданы в родительском процессе, но им не была предоставлена ​​возможность запуска.

% perl -wle 'use POE; POE::Session->create(inline_states=>{_start => sub {}})'
40023: Sessions were started, but POE::Kernel's run() method was never
40023: called to execute them.  This usually happens because an error
40023: occurred before POE::Kernel->run() could be called.  Please fix
40023: any errors above this notice, and be sure that POE::Kernel->run()
40023: is called.  See documentation for POE::Kernel's run() method for
40023: another way to disable this warning.

В приведенном выше примере 40023 — это идентификатор процесса, в котором была обнаружена проблема.

Это похоже на предупреждение Perl о выходе из активных потоков:

% perl -wle 'use threads; threads->create(sub { sleep 3600 }); '
Perl exited with active threads:
  1 running and unjoined
  0 finished and unjoined
  0 running and detached

Хотя ваш фрагмент кода показывает, что сеансы создаются и запускаются в дочернем процессе, я подозреваю, что сеансы создаются до или после.Родительский процесс не завершается в вашем фрагменте, поэтому неизвестно, куда пойдет выполнение дальше?

Вам также следует вызвать POE::Kernel->has_forked() в дочернем процессе.Я не могу сказать, происходит ли это в вашем фрагменте кода.

Правильное решение — переместить все экземпляры сеанса в дочерний процесс при демонизации.Приемлемым обходным путем является вызов POE::Kernel->run() сразу после использования POE::Kernel и до фактического создания каких-либо сеансов.run() немедленно завершит работу, поскольку сеансов не существует, но вызов удовлетворяет условию, о котором вас предупреждают.Это способ сказать «да-да, но я знаю, что делаю».

Другие советы

В документе запуск POE::Kernel обычно вызывается как метод класса;что такое $poe_kernel?

Кажется, что где-то вы начинаете сеанс, но не вызываете POE::Kernel->run();

Обновлять:поскольку сообщение, которое вы видите, выводится с предупреждением, а вы выбрасываете STDERR в дочернем элементе, я предполагаю, что предупреждение выдает родитель. Что-нибудь то, что вы делаете (в коде, который вы не показываете, который загружает POE и устанавливает $poe_kernel?), на самом деле создает сеанс, по-видимому, непреднамеренно.

Попытайтесь сократить свой код до короткого, но работоспособного примера, и вы либо сами обнаружите проблему, либо позволите другим помочь вам ее найти.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top