POE жалуется, что метод запуска POE::Kernel никогда не вызывался при разветвлении
Вопрос
Это мой код:
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?), на самом деле создает сеанс, по-видимому, непреднамеренно.
Попытайтесь сократить свой код до короткого, но работоспособного примера, и вы либо сами обнаружите проблему, либо позволите другим помочь вам ее найти.