in reply to STDERR Restore after redirect

I've written a module which attempts to make filehandle saving and restoring less problematic: IO::ReStoreFH. Perhaps it would help in your situation.

Replies are listed 'Best First'.
Re^2: STDERR Restore after redirect
by tultalk (Monk) on Apr 27, 2018 at 19:29 UTC

    Hi. I will take a look

    As it now stands, code below works except for one quirk.

    sub SendMemberMail { my ($subject,$from,$to,$port,$cc,$bcc,$heading,$body,$closing,$signi +ture,$auth) = @_; warn("In SendMemberMail before redirect of STDERR & STDOUT"); # Open log for recording during execution of SendMail my $sendMail_logfile = '/home/abcus/public_html/httpsdocs/cgi-bin/li +b/perl/Mail/mail.log'; open (my $fh, "+<", "$sendMail_logfile") or die "Opening: $!"; #Redirect STDERR & STDOUT to $fh for this sub open my $oldSTDOUT, ">&STDOUT"; open OLDERR, ">&",\*STDERR; open (STDERR, ">>&=", $fh) || die "can't redirect STDERR"; open (STDOUT, ">>&=", $fh) || die "can't redirect STDOUT"; $fh->autoflush(1); my $message = ($heading . "\n" . "\n" . $body . "\n" . "\n" . $closing . "\n" . "\n" . $signiture . "\n" ); if ($auth == 1) { $auth = {user=>'webmaster@abc.us', password=>'xx@33333XX', method= +>'PLAIN LOGIN', REQUIRED=>1} } elsif ($auth == 0) { $auth = ""; } my %mail = ( To => $to, From => $from, Cc => $cc, Bcc => $bcc, Auth => $auth, Port => $port, Subject => $subject, Message => $message, debug => 0 ); SendMail(%mail) or die $Mail::sendMail::error; $log .= "Sending eMail Succeded\n"; #Print the data from the $log. print $fh $log; #Test redirected handles print STDOUT "stdout 1\n"; warn("warn stderr 1\n"); close($fh); #restore the file standard handles open(STDOUT, ">&", $oldSTDOUT) or die "Can't dup \$oldout: $!"; open(STDERR, ">&OLDERR") or die "Can't dup OLDERR: $!"; #Test original handles print STDOUT "stdout 2\n"; warn("warn stderr 2\n"); return 1; }

    The mail is sent. The handles are restored as evidenced by stderr2 in my regular error log file and stderr/stdout in my pre-restore log file. What is gone in the nether world is the stdout2 and the printing of the HTML form to stdout back to client.

    If I don't close the handle, the form (text) is printed to the sendMail logfile.

    I put warns at beginning of the sub to print the html and at the end and both appear in the error log indicating execution of that block but no form returned to client.

    As I posted earlier, if I bypass the call to sendMail(), the form prints as expected.

    For some reason the call to print the form is not directed to the (opened)STDOUT nor to the (closed) $fh log handle. Perhaps lost in the mist of time and sitting at the earth moon L4 LaGrange point in a huge cloud of missing documents.

    I can't see anything in sendMail that could have such an effect. I shut off the debugging in sendMail which writes to stderr and no effect (except less output to the log naturally)

    I guess I have to just grunt my way through this until a revelation hits me.

    Scoping are weird!

      Just use local() within a block as tybalt89 suggested to save and then restore the filehandles.

      sub SendMemberMail { my ($subject,$from,$to,$port,$cc,$bcc,$heading,$body,$closing,$signi +ture,$auth) = @_; warn("In SendMemberMail before redirect of STDERR & STDOUT"); $Mail::sendMail::mailcfg{'debug'} = 6; $Mail::sendMail::mailcfg{'port'} = $port; my $message = "$heading\n\n$body\n\n$closing\n\n$signiture\n"; my %mail = ( To => $to, From => $from, Cc => $cc, Bcc => $bcc, Subject => $subject, Message => $message, ); if ($auth == 1) { $mail{'Auth'} = { user => '', password => '', method => 'PLAIN LOGIN', required => 1 }; }; my $logfile = '/home/abcus/public_html/httpsdocs/cgi-bin/lib/perl/Ma +il/mail.log'; open my $fh, '>>', $logfile or die "Error opening $logfile : $!"; SEND: { local *STDOUT = $fh; local *STDERR = $fh; if ( SendMail(%mail) ) { print $Mail::sendMail::log; } else { print $Mail::sendMail::error; } } close $fh; select STDOUT; # Test original handles print "stdout 2\n"; warn("warn stderr 2\n"); return 1; }
      Note: Using Mail::sendMail as described here
      poj

        Thanks

        I tried the local before and it did not work. Will try again

        I put some code in the sub that fails to print:

        sub CreateUserFeedbackForm { my ($message) = @_; if(!defined('STDOUT')){ warn("No STDOUT"); } elsif (defined('STDOUT')){ warn("STDOUT Defined"); } if(!defined('STDERR')) { warn("No STDOUT"); } elsif (defined('STDERR')) { warn("STDERR Defined"); }

        Result in my error log below:

        Fri Apr 27 16:43:31 2018 manage_users.cgi: STDOUT Defined at manage_users.cgi line 806. STDERR Defined at manage_users.cgi line 814. Fri Apr 27 16:43:31 2018 manage_users.cgi: STDERR Defined at manage_users.cgi line 814. At exit of sub CreateUserFeedbackForm at manage_users.cgi line 964. Fri Apr 27 16:43:31 2018 manage_users.cgi: At exit of sub CreateUserFeedbackForm at manage_users.cgi line 964.

        Since both returned "defined" my next question: Does that mean they are functional?

        I guess I could try writing to the handles to see but thought maybe some Monk could say "Yes defined means it is functional"

        Thanks

        <Hi>

        Thanks for input. As I stated before I already tried the local and the results were the same. So I tried again.

        Going through block of code and eliminating items step by step, commenting out #print "stdout 2\n"; and the program executed and printed html form as desired. Have no idea what effect that line could have to cause the failure. Ir was added for testing after some other problem.

        Bizarre/p>

        What is the SEND() for? What does it do?