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

My program has a Tk front end and allows users to invoke all sorts of functions via various widgets. If a function has a problem it can change the color of the LogFile widget to indicate trouble, and clicking the LogFile button opens the logfile for inspection.

I think I can live with all the functions dumping their various warnings and such into one file. My question is, if programs (under "my" control) are individually opening the logfile via '>>' for their error logging, what problems might I face? My goal is to interweave my log messages (via warn to a redirected STDERR) with any sort of system log messages.

As an example, the following program seems to "share" the file okay. What might beset me with this approach?

#!/usr/bin/perl -w # show two concurrent processes intermingling their STDERR to the same + file. # Name the program 'test_err.pl' and invoke it from command line with: # test_err.pl hs use strict; my $err_file = 'errfile.txt'; open STDERR, ">> $err_file" or die "cannot open initial $err_file: $!\n"; my $what_to_do = shift; warn "$what_to_do hello world\n"; system( 'test_err.pl', 'abc' ) if $what_to_do eq 'hs'; my $test_string; warn "success\n" if $test_string eq 'xyz'; warn "$what_to_do goodbye world\n"; # Adds the following text to 'errfile.txt': __DATA__ hs hello world abc hello world Use of uninitialized value in string eq at C:\aa\test_err.pl line 19. abc goodbye world Use of uninitialized value in string eq at C:\aa\test_err.pl line 19. hs goodbye world

Replies are listed 'Best First'.
Re: multiple programs sharing redirected STDERR
by gam3 (Curate) on Apr 26, 2005 at 17:23 UTC
    As long as you have line buffering, you should be OK.

    see $| and IO::Handle::setvbuf If you use the default settings with syswrite you should be ok. If you are on a system where this does not work you can add an flock around the syswrite.

    BEGIN { $SIG{'__WARN__'} = sub { syswrite STDERR, $_[0] } } warn "Warnings go to STDERR\n";

    Update: added example.

    -- gam3
    A picture is worth a thousand words, but takes 200K.
      Thanks, though this leads to more questions:

      1. The documentation describes $| as working with the currently selected output channel. STDERR also counts as the currently selected output channel?

      2. Documentation for IO::Handle seems to say that
      # setvbuf is not available by default on Perls 5.8.0 and later.

      The pod for Handle.pm goes on to say that:

      WARNING: The IO::Handle::setvbuf() is not available by default on Perls 5.8.0 and later because setvbuf() is rather specific to using the stdio library, while Perl prefers the new perlio subsystem instead +.
      From my ActiveState documentation, it does not look like this is included.

      Also, it looks like I can't use garden variety warn calls with IO::Handle, I'll need to change these all to object references? I assume system errors for STDERR will magically know to write to the designated file?

          1. The documentation describes $| as working with the currently selected output channel. STDERR also counts as the currently selected output channel?

        I believe STDOUT is the default 'currently selected output channel'. See the description of 'select' in the Camel. (It's on page 210 of my very old version.)

        --
        tbone1, YAPS (Yet Another Perl Schlub)
        And remember, if he succeeds, so what.
        - Chick McGee

Re: multiple programs sharing redirected STDERR
by graff (Chancellor) on Apr 27, 2005 at 02:54 UTC
    You mentioned "users" (plural)... if two or more people are using the same script simultaneously, and "errfile.txt" is the same path for all of them, you'll have trouble (users will be misinformed and confused by the file's content).

    That's easy to fix by making sure that every run uses a unique file name for its log file.

      I should say, I'm "hoping" for users. :-)

      The program is a single-user tool for a W32 platform. It installs in a user-specified/owned folder and therefore, even with the same relative path name, would be unique from user to user. When the need arises to get this "Enterprise-ready", it will still be a matter of each user's config files (and thus his/her log file) being in their own directory/folder. You make a good point that I hadn't considered directly.

      But also, by your going along with "one log file per user/run", it looks okay to you to proceed with this sort of STDERR inheritance scheme. :-)

Re: multiple programs sharing redirected STDERR
by gam3 (Curate) on Apr 27, 2005 at 14:47 UTC
    Here is code that uses syswrite to write out warnings STDERR. This should allow multiple programs to write to the same file without the need for locking. It would also be easy to use a different file handle than STDERR to output warnings if wanted.

    It is possible that this code will not work on all systems.

    -- gam3
    A picture is worth a thousand words, but takes 200K.
      Okay, so the reason to use 'syswrite' is that it bypasses buffered IO, and therefore I have higher likelihood of avoiding any kind of conflict as one routine and then the next write to STDERR? And in this case '$|' is extraneous?

      I noticed that documentation for 'syswrite' says it processes a single scalar parameter and that 'warn' handles a list. Yet when I broke my example's warn strings into a list of two parameters, the 'syswrite' seemed to print everything that 'warn' was given. Is it somehow scooping up all those parameters as individual scalars to 'syswrite' against?

      Regarding naming the filehandle differently from STDERR: If I do so won't that be misleading since all the normal STDERR-bound things like 'warn' and various warnings from the system will go to the designated filehandle, and a print STDERR 'some warning' would not be mixing with the other warnings? I guess it's a matter of perspective.

      Suppose a user opens the logfile with Notepad or vim, and does some editing. To do so while the Tk frontend of the program is open, not doing anything because the user hasn't invoked any functions recently via a widget, still sounds suboptimal since the program itself still has hooks with the logfile via the ">>" open. Within my program, when users open the file via my button (invoking Notepad or vim via a 'system' call), they can't get anything else to happen, and so my program won't be competing for the ability to write to that logfile. Is allowing users to access the subject file likely to confuse 'syswrite'? I notice that p. 813 of my Camel book says:

      Because syswrite bypasses the C standard I/O library, do not mix calls to it with reads (other than sysread, writes (like print, printf, or write, or other stdio functions like seek, tell, or eof unless you are into heavy wizardry.