Pergunta

This is my code:

 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;
      }

When $DAEMON = 1, it complains that POE::Kernel's run() method was never called, but as you can see in the above code, I did that already. The script works perfectly fine when in daemon mode, but I can't get rid of that warning or understand why it says that. I also tried calling $poe_kernel->has_forked() and that didn't make a difference either.

I'm out of ideas. Any suggestions?

Updated to add: Maybe I wasn't clear enough. The code below creates the session and runs the kernel.

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

It works perfectly fine. It's only when the same code is run inside a fork'd child so I can send the script to the background, that it says POE::Kernel's run method wasn't called. The script does go into the background and works like it should which means the kernel is indeed running. I'm only looking to get rid of that annoying warning.

Foi útil?

Solução

ysth is right. The warning happens because POE::Session instances are created in the parent process but they haven't been given an opportunity to run.

% 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.

In the above example, 40023 is the process ID where the problem was detected.

It's similar to Perl's warning about exiting with active threads:

% 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

While your code snippet shows sessions are created and run in the child process, I suspect sessions are created before or afterward. The parent process doesn't exit in your snippet, so there's no telling where execution goes afterward?

You should also call POE::Kernel->has_forked() in the child process. I can't tell whether that's happening in your code snippet.

The correct solution is to move all session instantiation into the child process when daemonizing. A passable workaround is to call POE::Kernel->run() just after using POE::Kernel and before any sessions are actually created. run() will return immediately because no sessions exist, but the call satisfies the condition you're being warned about. It's a way of saying "yes, yes, but I know what I'm doing".

Outras dicas

From the doc, POE::Kernel's run is normally called as a class method; what is $poe_kernel?

Somewhere, you seem to be starting a session but don't end up calling POE::Kernel->run();

Update: since the message you see is output with warn, and you are throwing away STDERR in the child, I'm guessing it is the parent giving the warning. Something you are doing (in the code you don't show that loads POE and sets $poe_kernel?) is in fact creating a session, apparently unintentionally.

Try to reduce your code to a short, yet runnable example and you will either find the problem yourself or enable others to help you find it.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top