jarthda has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a script running on win32 system that uses a change notification to wait for files to process. My first issue is keeping a logfile up to date in the loop. I have found that if the script is interupted or closed via task manager then much of the log file is lost. I resolved this by putting open and close commands before and after each log entry. I figure there must be a more graceful way.

Replies are listed 'Best First'.
Re: writing to logfile in a loop
by sgifford (Prior) on Nov 21, 2006 at 20:01 UTC
      The second method requires IO::Handle to be loaded (directly or otherwise).
Re: writing to logfile in a loop
by blue_cowdawg (Monsignor) on Nov 21, 2006 at 20:34 UTC
        I have found that if the script is interupted or closed via task manager then much of the log file is lost.

    Observe the following code:

    use IO::Handle; use strict; $|=1; my $io=new IO::Handle; open LOG,">> mylofile.txt" or die "mylogfile.txt: $!"; $io->fdopen(fileno(LOG),"w+") or die $!; $io->autoflush(1); my $foo=0; while(1){ $foo++; printf "Iteration: %d\n",$foo; $io->printf("Looped in %d\n",$foo); sleep 2; }

    I normally don't do Windows, but since I had a VMWare session going I fired up a quick test of your problem. Ran the above code and killed it with the Task Manager and no data was harmed in the making of rhis node. (Everything I expected was in the log file!)


    Peter L. Berghold -- Unix Professional
    Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg

      That's needlessly complicated. LOG and $io? autoflush and other IO::Handle methods can be used on any file handle, including barewords. That means that only LOG is needed. Or better yet, a lexical var ($log).

      use strict; use warnings; use IO::Handle; my $log_file = 'mylogfile.txt'; open my $log, '>>', $log_file or die "Unable to open log file \"$log_file\": $!\n"; STDOUT->autoflush(1); $log->autoflush(1); my $foo=0; while(1){ $foo++; printf "Iteration: %d\n",$foo; $log->printf("Looped in %d\n",$foo); # or printf $log ... sleep 2; }

      I also

      • improved the error message,
      • used the safer 3-arg open,
      • made the log file name easily editable, and
      • avoided the cryptic $|.

        Actually, I tried just that prior to my post. It errored out on me. Possibly the version of Perl that was installed on my VMWare virtual machine is at fault. At any rate if it works for you, use it. If not, my solution is just as valid.

        Not sure I understand your comment about $| being cryptic. Seems like Perl 101 to me...


        Peter L. Berghold -- Unix Professional
        Peter -at- Berghold -dot- Net; AOL IM redcowdawg Yahoo IM: blue_cowdawg
Re: writing to logfile in a loop
by wojtyk (Friar) on Nov 21, 2006 at 22:14 UTC
    On a side note, you could also install a signal handler.
    I believe Task Manager just sends a SIGTERM.
    You could always catch the signal and then close your handles gracefully.

      I believe Task Manager just sends a SIGTERM.

      There's no such thing as signals in Windows. The closest parallel is the message queues of windows.

      Furthermore, Task Manager's behaviour varies depending on which tab ("Applications" or "Processes") the item being terminated is located.

      When "ending" a "Process", the application is forcibly terminated. ( Reference: TerminateProcess(hProcess, uExitCode) )

      When "ending" an "Application", it sends a WM_QUIT WM_CLOSE message to the window. If the application is still running after a small period of time, the user is told the process is not responding, and he is asked whether he wants to terminate the process or not. If the user chooses to terminate the process, it is forcibly terminated. ( Reference: EndTask(hWnd, FALSE, TRUE) )

        Is Perl capable of handling Windows messaging? I know that if you were writing a Windows app, you could just have a message loop and handle the WM_CLOSE message.

      Windows does not use UNIX signals.

      This is a piece of Windows software that sends various kinds of close commands to windows programs. It can send specifics including WM_CLOSE and SC_CLOSE. I believe that TaskManager uses User32.dll->EndTask().

      Check this out, it can kill anything:

      Advanced Process Termination