Hi,

Here is a patch against the SVN head.

Changes:
- fixes incompatibility with fork() : END {} block executed only in the main 
thread.
- fixes white spaces in POD
- changes to go towards 'strict' mode

Olivier Mengué
dol...@cpan.org


Index: Daemon.pm
===================================================================
--- Daemon.pm   (revision 485)
+++ Daemon.pm   (working copy)
@@ -3,12 +3,14 @@
 #//  Daemon.pm
 #//  Win32::Daemon Perl extension package file
 #//
-#//  Copyright (c) 1998-2002 Dave Roth
+#//  Copyright (c) 1998-2008 Dave Roth
 #//  Courtesy of Roth Consulting
 #//  http://www.roth.net/
 #//
-#//  This file may be copied or modified only under the terms of either 
-#//  the Artistic License or the GNU General Public License, which may 
+#//  Copyright (c) 2009 Olivier Mengue
+#//
+#//  This file may be copied or modified only under the terms of either
+#//  the Artistic License or the GNU General Public License, which may
 #//  be found in the Perl 5.0 source kit.
 #//
 #//  2008.03.24  :Date
@@ -17,21 +19,25 @@
 
 package Win32::Daemon;
 
-$PACKAGE = $Package = "Win32::Daemon";
 
-$VERSION = 20080324;
+#use strict;
+#use warnings;
+our $PACKAGE = $Package = "Win32::Daemon";
+
+our $VERSION = 20080324;
 require Exporter;
 require DynaLoader;
+use vars qw( $AUTOLOAD );
 
 my @OSVerInfo = Win32::GetOSVersion();
 my $OSVersion = "$OSVerInfo[1].$OSVerInfo[2]";
 my $RECOGNIZED_CONTROLS;
 
-...@isa= qw( Exporter DynaLoader );
+our @ISA= qw( Exporter DynaLoader );
     # Items to export into callers namespace by default. Note: do not export
     # names by default without a very good reason. Use EXPORT_OK instead.
     # Do not simply export all your public functions/methods/constants.
-...@export = qw(
+our @EXPORT = qw(
 
     SERVICE_CONTROL_USER_DEFINED
     SERVICE_NOT_READY
@@ -60,7 +66,7 @@
     SERVICE_CONTROL_SESSIONCHANGE
     SERVICE_CONTROL_USER_DEFINED
     SERVICE_CONTROL_RUNNING
-    SERVICE_CONTROL_PRESHUTDOWN 
+    SERVICE_CONTROL_PRESHUTDOWN
     SERVICE_CONTROL_TIMER
     SERVICE_CONTROL_START
 
@@ -82,8 +88,8 @@
 
     SERVICE_ACCEPT_STOP
     SERVICE_ACCEPT_PAUSE_CONTINUE
-    SERVICE_ACCEPT_SHUTDOWN    
-    SERVICE_ACCEPT_PARAMCHANGE  
+    SERVICE_ACCEPT_SHUTDOWN
+    SERVICE_ACCEPT_PARAMCHANGE
     SERVICE_ACCEPT_NETBINDCHANGE
 
     SERVICE_WIN32_OWN_PROCESS
@@ -109,12 +115,11 @@
 );
 
 
-...@export_ok = qw(
-);      
+our @EXPORT_OK = ();
 
-bootstrap $Package;
+bootstrap(__PACKAGE__);
 
-sub AUTOLOAD 
+sub AUTOLOAD
 {
     # This AUTOLOAD is used to 'autoload' constants from the constant()
     # XS function.  If a constant is not found then control is passed
@@ -138,9 +143,8 @@
         # $Result == 1 if the constant is valid but not defined
         # that is, the extension knows that the constant exists but for
         # some wild reason it was not compiled with it.
-        $pack = 0; 
-        ($pack,$file,$line) = caller;
-        print "Your vendor has not defined $Package macro $constname, used in 
$file at line $line.";
+        my ($pack,$file,$line) = caller;
+        print "Your vendor has not defined ".__PACKAGE__." macro $Constant, 
used in $file at line $line.";
     }
     elsif( 2 == $Result )
     {
@@ -160,7 +164,8 @@
 
 END
 {
-    Win32::Daemon::StopService();
+    # Stop the service only if we are in the main thread (not in a forked 
process)
+    Win32::Daemon::StopService() if $$ > 0;
 }
 
 __END__
@@ -237,7 +242,7 @@
 This function queries (and optionally sets) the current list of controls that 
the service registers for.
 By registering for a control the script is notifying the SCM that it is 
accepting the specified
 control messages. For example, if you specify the 
C<SERVICE_ACCEPT_PAUSE_CONTINUE> control then
-the SCM knows that the script will accept and process any attempt to pause and 
continue (resume 
+the SCM knows that the script will accept and process any attempt to pause and 
continue (resume
 from paused state) the service.
 
 Recognized accepted controls:
@@ -250,13 +255,13 @@
 
 Following controls are only recognized on Windows 2000 and higher:
 
-    SERVICE_ACCEPT_PARAMCHANGE........The service accepts messages notifying 
it of any 
+    SERVICE_ACCEPT_PARAMCHANGE........The service accepts messages notifying 
it of any
                                       parameter change made to the service.
-    SERVICE_ACCEPT_NETBINDCHANGE......The service accepts messages notifying 
it of any 
+    SERVICE_ACCEPT_NETBINDCHANGE......The service accepts messages notifying 
it of any
                                       network binding changes.
 
 By default all of these controls are accepted. To change this pass in a value 
consisting of
-any of these values OR'ed together. 
+any of these values OR'ed together.
 
 B<NOTE> that you can query and set these controls at any time. However it is 
only supported to
 set them before you start the service (calling the C<StartService()> function).
@@ -268,8 +273,8 @@
 that the calling of this routine will be blocked by any other callback.
 
 If you pass in a value it will reset the timer to the specified frequency. 
Passing in
-a 0 will disable all "Running" callbacks. Passing in -1 will toggle the state 
between 
-calling the "Running" callback subroutine and not calling it. 
+a 0 will disable all "Running" callbacks. Passing in -1 will toggle the state 
between
+calling the "Running" callback subroutine and not calling it.
 
 =item CreateService ( \%Hash )
 
@@ -291,12 +296,12 @@
 The 'display' service name; that is, the name displayed
 by the services control panel or MMC plugin.
 
-=item path 
+=item path
 
 The full path name to the executable. This should be the path to your Perl
 executable, which will normally be the contents of $^X.
 
-B<NOTE:> If you are using a compiled perl script (such as one 
+B<NOTE:> If you are using a compiled perl script (such as one
 generated with PerlApp) as opposed to a text based perl script file then this
 value must point to the actual compiled script's executable (eg. 
MyCompiledPerlService.exe)
 instead of ($^X which usually points to perl.exe). You can specify
@@ -386,7 +391,7 @@
 =item GetSecurity( $Machine, $ServiceName )
 
 This will return a binary Security Descriptor (SD) that is associated with the
-specified service on the specified machine. 
+specified service on the specified machine.
 
 The SD is in self-relative format. It can be imported into a Win32::Perms 
object using
 the Win32::Perms object's Import() method.
@@ -399,7 +404,7 @@
 service. Not all events must have callbacks registered.
 
 If only a reference to a subroutine is passed in then it will be called for 
each and every
-event. You can pass in a hash containing particular key names (listed below) 
with 
+event. You can pass in a hash containing particular key names (listed below) 
with
 code references.
 
 Possible hash key names:
@@ -424,7 +429,7 @@
     power_event..............A power event has occured (eg change to battery 
power).
     session_change...........There has been a change in session.
     user_defined.............A user defined event has been sent to the service.
-    
+
 NOTE: The 'Stop' state. When a service calls into the registered "stop" 
callback routine
 the script should call the C<StopService()> function. This tells the service 
to terminate
 and return back to the Perl script. This is the only way for the service to 
know that it
@@ -433,7 +438,7 @@
 Note: The 'Running' state. Periodically the extension will call into a 
registered
 "Running" subroutine. This allows the script to process data. This routine 
should be fast
 and return quickly otherwise it will block other callback events from being 
run. The
-frequency of calling the "Running" subroutine is dictated by the callback 
timer value 
+frequency of calling the "Running" subroutine is dictated by the callback 
timer value
 passed into C<StartService()> and any changes made to this value by calling 
into
 C<CallbackTimer()>.
 
@@ -463,7 +468,7 @@
 =item Callback Mode
 
 If the script has already registered callback routines (using 
C<RegisterCallbacks()>) then
-the call into C<StartService()> will not return until the service has stopped. 
However 
+the call into C<StartService()> will not return until the service has stopped. 
However
 callbacks will be made for each state change and callback timer timeout (refer 
to C<RegisterCallbacks()>).
 
 =back
@@ -484,7 +489,7 @@
 Pass in a non zero value to reset the pending message to 
C<SERVICE_CONTROL_NONE>. This way
 your script can tell when two of the same messages come in.
 
-Occasionally the service manager will send messages to the service. These 
messages 
+Occasionally the service manager will send messages to the service. These 
messages
 typically request the service to change from one state to another.  It is 
important that
 the Perl script responds to each message otherwise the service manager becomes 
confused
 about the current state of the service. For example, if the service manager is 
submits
@@ -502,11 +507,11 @@
                                       This results in State() reporting 
SERVICE_STOP_PENDING.
     SERVICE_CONTROL_PAUSE.............The SCM is requesting the service to 
pause.
                                       This results in State() reporting 
SERVICE_PAUSE_PENDING.
-    SERVICE_CONTROL_CONTINUE..........The SCM is requesting the service to 
continue from a 
+    SERVICE_CONTROL_CONTINUE..........The SCM is requesting the service to 
continue from a
                                       paused state.
                                       This results in State() reporting 
SERVICE_CONTINUE_PENDING.
     SERVICE_CONTROL_INTERROGATE.......The service manager is querying the 
service's state
-    
+
     SERVICE_CONTROL_USER_DEFINED......This is a user defined control. There 
are 127 of these
                                       beginning with 
SERVICE_CONTROL_USER_DEFINED as the base.
     Windows 2000 specific messages:
@@ -524,7 +529,7 @@
     SERVICE_CONTROL_HARDWAREPROFILECHANGE..A change has been made to the 
system's hardware profile.
     SERVICE_CONTROL_POWEREVENT........A power event has occured (eg change to 
battery power).
     SERVICE_CONTROL_SESSIONCHANGE.....There has been a change in session.
- 
+
     Windows Vista + specific messages:
     SERVICE_CONTROL_PRESHUTDOWN ......The machine is about to shut down. This 
provides the service
                                       much more time to shutdown than 
SERVICE_CONTROL_SHUTDOWN.
@@ -534,8 +539,8 @@
 B<Note:> When the system shuts down it will send a C<SERVICE_CONTROL_SHUTDOWN> 
message. The
 Perl script has approximately 20 seconds to perform any shutdown activities 
before the
 Control Manger stops the service. If more time is needed call the C<State()> 
function
-passing in the C<SERVICE_STOP_PENDING> control message along with how many 
seconds it will 
-take to shutdown the service. This time value is only an estimate. When the 
service is 
+passing in the C<SERVICE_STOP_PENDING> control message along with how many 
seconds it will
+take to shutdown the service. This time value is only an estimate. When the 
service is
 finally ready to stop it must submit the C<SERVICE_STOPPED> message as in:
 
     if( SERVICE_CONTROL_SHUTDOWN == State() )
@@ -558,7 +563,7 @@
 for 30 seconds for the script to change the service's state before deciding 
that the
 script is non responsive.
 
-If you are setting/updating the state instead of passing in the state and wait 
hint you could 
+If you are setting/updating the state instead of passing in the state and wait 
hint you could
 pass in a hash reference. This allows you to specify the state, wait hint and 
error state. You
 can use the following keys:
 
@@ -566,7 +571,7 @@
     --------
     state..........Valid service state (see table below).
     waithint.......A wait hint explained above. This is in milliseconds.
-    error..........Any 32 bit error code. This is what will be reported if an 
application 
+    error..........Any 32 bit error code. This is what will be reported if an 
application
                    queries the error state of the service. It is also what is 
reported if
                    a call to start the services fails.
                    To reset an error state pass in NO_ERROR.
@@ -585,7 +590,7 @@
        ---------------------
     SERVICE_NOT_READY..........The SCM has not yet been initialized. If the 
SCM is slow or busy
                                then this value will result from a call to 
State().
-                               If you get this value, just keep calling 
State() until you get 
+                               If you get this value, just keep calling 
State() until you get
                                SERVICE_START_PENDING.
     SERVICE_STOPPED............The service is stopped
     SERVICE_RUNNING............The service is running
@@ -601,15 +606,15 @@
 
 Callbacks were introduced in version v20030617.
 
-The Win32::Daemon supports the concept of event callbacks. This allows a 
script to 
+The Win32::Daemon supports the concept of event callbacks. This allows a 
script to
 register a particular subroutine with a particular event. When the event 
occurs it
 will call the Perl subroutine registered with that event. This can make it 
very simple
 to write scripts.
 
 You register a callback subroutine by calling into the C<RegisterCallbacks()> 
function.
 You can pass in a code reference or a hash. A code reference will register the 
specified
-subroutine with all events. A hash allows you to pick which events you want to 
-register for which subroutines. You do not have to register all events. If an 
event is 
+subroutine with all events. A hash allows you to pick which events you want to
+register for which subroutines. You do not have to register all events. If an 
event is
 not registered for a subroutine then the script will not be notified when the 
event
 occurs.
 
@@ -623,14 +628,14 @@
 that it is offically paused.
 
 Once callback subroutines are registered the script enters the service mode by 
calling
-C<StartService()>. This will being the process of calling the event callback 
routines. 
-Note that when callback routines are registered the C<StartService()> function 
will not 
+C<StartService()>. This will being the process of calling the event callback 
routines.
+Note that when callback routines are registered the C<StartService()> function 
will not
 return until a callback routine calls C<StopService()> (typically the 'Stop' 
event callback
 would call C<StopService()>.
 
 When calling into C<StartService()> you can pass in a hash reference. This 
reference is known as
 a "context" hash. For every callback the hash will be passed into the callback 
routine. This enables
-a script to query and set data in the hash--essentially letting you pass 
information across to 
+a script to query and set data in the hash--essentially letting you pass 
information across to
 different callback events. This context hash is not required.
 
 When a callback is made it always passes two parameters in: $State and 
$Context. $State is simply
@@ -644,9 +649,9 @@
     {
         my( $Event, $Context ) = @_;
         $Context->{last_event} = $Event;
-        
+
         # ...do some work here...
-        
+
         # Tell the service manager that we have now
         # entered the running state.
         Win32::Daemon::State( SERVICE_RUNNING );
@@ -659,31 +664,31 @@
 =head1 Compiled Perl Applications
 
 Many users like to compile their perl scripts into executable programs. This 
way it is much easier to copy them around
-from machine to machine since all necessary files, packages and binaries are 
compiled into one .exe file. These compiled 
+from machine to machine since all necessary files, packages and binaries are 
compiled into one .exe file. These compiled
 perl scripts are compatible with Win32::Deamon as long as you install it 
correctly.
 
-If you are going to compile your Win32::Daemon based perl script into an .exe 
there is nothing unique you need to do 
+If you are going to compile your Win32::Daemon based perl script into an .exe 
there is nothing unique you need to do
 to your Win32::Daemon code with one single exception of the call into 
Win32::Daemon::C<CreateService()>. When passing in
 the 'path' and 'parameters' values into C<CreateService()> observe the 
following simple rules:
 
 =over 4
 
     1) If using a Perl script
-      path........The full path to the Perl interpeter (perl.exe). 
+      path........The full path to the Perl interpeter (perl.exe).
                   This is typically:
                      c:\perl\bin\perl.exe
-             
-      parameter...This value MUST start with the full path to the 
+      
+      parameter...This value MUST start with the full path to the
                   perl script file and append any parameters
                   that you want passed into the service. For
                   example:
                   c:\scripts\myPerlService.pl -param1 -param2 "c:\\Param2Path"
     
     2) If using a compiled Perl application
-      path........The full path to the compiled Perl application. 
+      path........The full path to the compiled Perl application.
                   For example:
                   c:\compiledscripts\myPerlService.exe
-             
+      
       parameter...This value is just the list of  parameters
                   that you want passed into the service. For
                   example:
@@ -768,7 +773,7 @@
     {
       # The service is running as normal...
       # ...add the main code here...
-         
+
     }
     else
     {
@@ -806,17 +811,17 @@
 
 =head2 Example 3: Install the service
 
-For the 'path' key the $^X equates to the full path of the 
+For the 'path' key the $^X equates to the full path of the
 perl executable.
 Since no user is specified it defaults to the LocalSystem.
 
-    use Win32::Daemon; 
-    # If using a compiled perl script (eg. myPerlService.exe) then 
+    use Win32::Daemon;
+    # If using a compiled perl script (eg. myPerlService.exe) then
     # $ServicePath must be the path to the .exe as in:
     #    $ServicePath = 'c:\CompiledPerlScripts\myPerlService.exe';
     # Otherwise it must point to the Perl interpreter (perl.exe) which
     # is conviently provided by the $^X variable...
-    my $ServicePath = $^X; 
+    my $ServicePath = $^X;
     
     # If using a compiled perl script then $ServiceParams
     # must be the parameters to pass into your Perl service as in:
@@ -878,7 +883,7 @@
             # ... note that here there is no need to
             #     change the state
             
-        }    
+        }
         elsif( SERVICE_START_PENDING == $Event )
         {
             # Initialization code
@@ -951,7 +956,7 @@
             # ... note that here there is no need to
             #     change the state
         }
-    }    
+    }
 
     sub Callback_Start
     {
@@ -1020,6 +1025,13 @@
 
 =head1 HISTORY:
 
+    - 20091028 Olivier Mengue
+        -Disabled END {} in non-main threads to fix bug RT#50020
+        -Changes to go to 'strict' mode.
+        -Fixed white spaces in POD.
+
+    - 20080321 rothd
+
     - 20011205 rothd
         -Fixed bug where "invalid service state 80" is reported in the Win32 
event log.
         -Added initial support for SCM request callbacks (this is not 
implemented fully and
@@ -1038,11 +1050,11 @@
             SERVICE_ACCEPT_SESSIONCHANGE
 
     - 20011221 ro...@roth.net
-        - Fixed bug where service doesn't work properly with Windows NT 4. We 
were 
-          defaulting by acccepting the SERVICE_ACCEPT_PARAMCHANGE and 
-          SERVICE_ACCEPT_NETBINDCHANGE controls. However, they were introduced 
in 
+        - Fixed bug where service doesn't work properly with Windows NT 4. We 
were
+          defaulting by acccepting the SERVICE_ACCEPT_PARAMCHANGE and
+          SERVICE_ACCEPT_NETBINDCHANGE controls. However, they were introduced 
in
           Win2k so NT 4 coughed up blood with them.
-    
+
     - 20020108 ro...@roth.net
         - Fixed another bug wwhere servie wouldn't work on Win2k machines. We
           were treating Win2k (version 5.0) the same as WinXP (version 5.1) and
@@ -1050,15 +1062,15 @@
           start, pause or stop. Fix was only in the Daemon.pm file.
 
     - 20020114 marc.pijnapp...@nec-computers.com
-        - Fixed another bug where service wouldn't work on WinXP machines. 
Variable 
-          recognized_controls was wrongly initialized for WinXP systems. This 
-          rendered the service unable to start, pause or stop. Fix was only in 
+        - Fixed another bug where service wouldn't work on WinXP machines. 
Variable
+          recognized_controls was wrongly initialized for WinXP systems. This
+          rendered the service unable to start, pause or stop. Fix was only in
           the Daemon.pm file.
 
     - 20020605 ro...@roth.net
         - Added support for reporting service errors. You can now pass in a
           hash reference into State(). More details in the POD docs.
-          
+
     - 20030617 ro...@roth.net
         - Added support for querying and setting service security. This 
includes
           DACL and SACL support. Due to complexity and failures you can not set
@@ -1067,7 +1079,7 @@
           - SetSecurity()
         - Finished incorporating callback routines.
         - Added a few more events.
-              
+
        - 20080321      ro...@roth.net
           -Callbacks can now return a state value. This is the functional 
equivilent of calling 
            Win32::Daemon::State( $NewState ) before returning:
@@ -1089,11 +1101,8 @@
          -Callback timer works correctly!
          -CALLBACK_RUNNING has been depreciated and replaced with 
CALLBACK_TIMER. It is only called
           when the timer (set by CallbackTimer()) has expired. Use this as a 
heartbeat. You only need
-          to set it once either with CallbackTimer() or passing in the timer 
value when calling into 
+          to set it once either with CallbackTimer() or passing in the timer 
value when calling into
           StartService().
           Set the callback using "timer" as the callback name. Using "running" 
will also work but it
           is mapped to "timer". If you specify both, only "timer" will be 
registered.
-          
-          
- 
        
\ No newline at end of file
===================================================================

Reply via email to