1

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.

perlit
  • 329
  • 4
  • 13

2 Answers2

2

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

Rocco Caputo
  • 104
  • 3
  • This fixed an issue for me. I think POE::Component::Resolver sets itself up on import - if you fork, POE will complain and the child process won't work properly. If you call $poe_kernel->run in the child process, the resolver shuts down and the fork works correctly. – rjh Feb 22 '11 at 16:34
1

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.

ysth
  • 96,171
  • 6
  • 121
  • 214
  • 1
    $poe_kernel is the same as POE::Kernel. run() needs to be called only once after all the sessions are started. The warning is there only when I do it inside the fork()'d child. – perlit Dec 31 '10 at 18:24