Thanks for all of the messages for my problem with an NT service that is
compiled using the ActiveState PDK 5.1 stopping when the user logs out of
the operating session.

I found the solution after the posting from Andrew Chen, regarding the
signals that a POE application needs to handle when a session is
terminating. I printed out the name of the signal from the default
_signal() event handler for non-handled events and it would seem that
Windows sends a QUIT signal (SIGQUIT or WM_QUIT?) to each POE session and
if it is not handled the service will terminate.

The solution is simply to register a signal handler for 'QUIT' using sig()
and fire the sig_handled() method in that handler and all works fine. 

I have had a number of emails about this problem, so I am posting my
simplified test script that shows both how to run POE with ActiveState's
PDK and the solution to the session logout problem:

#
# Simple application to test session logout with POE and ActiveState Perl
PDK service
# and demonstrate how to use POE with the ActiveState PDK
#
# Dr. Harley Mackenzie
# [EMAIL PROTECTED]
# HARD software
#
# Runs as interactive application and NT service using ActiveState PDK 5.1
#
# call perlsvc --force --verbose poetest.pl --add
POE::Kernel;POE::Session;POE::Wheel;POE::Driver::SysRW;POE::Filter::Line;POE::Wheel::ReadWrite;POE::Filter::Stream;
--trim POE::Loop::Tk;POE::Loop::Gtk
#
# NOTE:
#   For PerlSvc to run properly, all POE module source MUST be
preprocessed - see POE::Preprocessor manpage
#

package PerlSvc;

use strict;
use warnings;
use POE;

our %Config;
our $LOGFILE = 'c:/nas/poetest/poetest.log'; # MUST be absolute path -
change to suit local directory structure
our $DELAY = 1;
our $ALIAS = 'dirwatch';

use IO::File;

unless (defined &ContinueRun) {
  *ContinueRun      = sub { return 1 };
  *RunningAsService = sub { return 0 };
  Interactive();
}

sub Startup {
  my $log = IO::File->new("> $LOGFILE"); 
  $log->autoflush(1);
  STDOUT->autoflush(1) unless RunningAsService();

  POE::Session->new(
    _start => sub {
      my $kernel = $_[KERNEL];
      $kernel->alias_set($ALIAS);
      $kernel->sig(QUIT => 'event_quit'); #### REMOVE this line to show
that the service DOES stop during session logout
      $kernel->delay_set(checkdir => $DELAY);
    },
    event_quit => sub { # windows sends SIGQUIT to application during
logout
      my ($kernel) = $_[KERNEL];
      print $log "SIGQUIT signal received - handled\n";
      $kernel->sig_handled();
    },
    checkdir => sub {
      my($kernel) = $_[KERNEL];

      my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =
localtime(time);
      $year += 2000; ++$mon;
      my $timestr = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $year, $mon,
$mday, $hour, $min, $sec);
      print $log "checkdir '$timestr'\n" if $log;
      print "." unless RunningAsService();

      if (ContinueRun()) {
        $kernel->delay_set(checkdir => $DELAY);
      }
      else {
        print $log "No ContinueRun() state\n";
      }
    },
  );
    
  $poe_kernel->run();

  $log->close;
}

sub Pause {
}

sub Continue {
}

sub Interactive {
  Install();
  Startup();
}

sub Install {
  $Config{'ServiceName'} = "POETest";
  $Config{'DisplayName'} = "POETest for logout bug";

  print "\nInstalling service\n";
}

sub Remove {
  $Config{'ServiceName'} = "POETest";

  print "\nRemoving service\n";
}

sub Help {
  print "\nHelp called\n";
}

package main;



Reply via email to