http://www.perlmonks.org?node_id=953929

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

Hi,

After some months of testing I *think* the reason why my script hangs is due to race condition in Mail::Sender::MailMsg

My diagnositic messages suggest that if my internet connection goes down while executing MailMsg() my script never returns from MailMsg

Is there any way of enforcing a timeout on MailMsg? (And also MailFile?)

As this is not the kind of problem I can readily duplicate I won't try to make a minimal script to demonstrate it, but will insert my current code in case it is useful. Hopefully the variable names are self-explanatory.

(This is for a network monitoring application which sends me email when it sees changes to various variables including the external ip address of my ADSL router. Normally if the internet connection is down new Mail::Sender() fails with an appropriate error. However, occasionally the sender object is created OK but it seems that MailMsg() doesn't return. For many months I have experienced my script hanging very occasionally and always about the same time the router's external ip address changes, although usually it handles an ip address change with no problem)

I HAVE tried a trivial piece of test code which does new Mail::Sender() then sleeps for 20 seconds before executing MailMsg() during which period I bring down the adsl connection at the router. However that works satisfactorally as MailMsg produces error -3

Error sending mail: Error code -3 (connect() failed: Invalid argument)

Code which was running when the script hung this morning:

sub sendmail { my ($arg_ref) = @_; print "Running sendmail()\n" if ($onterm && ($debug & $DEBUG_NOTIFY_ +MAILS)); =pod This subroutine is the interface to the mail sender functionality. Depending on incoming parameters it sends just a message or a message + with attachment =cut my $sendfailed = 0; my $sender = new Mail::Sender( {from => $arg_ref->{from}, smtp => $arg_ref->{smtp}, port => $arg_ref->{port}, auth => $arg_ref->{auth}, authid => $arg_ref->{authid}, authpwd => $arg_ref->{authpwd}, auth_encoded => $arg_ref->{auth_encoded}, encoding => 'Quoted-printable', charset => $charset, }); if ($sender > 0) { print "\$sender created OK\n" if ($onterm && ($debug & $DEBUG_NOTIFY +_MAILS)); if ((defined $arg_ref->{file}) && (-f $arg_ref->{file})) { # Sen +d message with attachment print "sending mail with attachment\n" if ($onterm && ($debug & $DEB +UG_NOTIFY_MAILS)); $sender->MailFile({to => $arg_ref->{to}, subject => $arg_ref->{subject}, encoding => "Base64", ## read this from parameters? msg => encode($charset,$arg_ref->{msg}), file => $arg_ref->{file} }); if (defined $sender->{'error'} ){ logerror( "Error sending mail with attachment '$arg_ref->{file}' t +o $arg_ref->{to}: Error code $sender->{'error'} ($sender->{'error_msg +'})"); $sendfailed = 1; } else { loginfo("File \"$arg_ref->{file}\" successfully emailed to $arg_re +f->{to}"); } } else { #send a message with no attachment $arg_ref->{msg} .= "\n\nAttempt to send file '$arg_ref->{file}' + abandoned: File does not exist" if defined $arg_ref->{file}; print "sending mail without attachment\n" if ($onterm && ($debug & $ +DEBUG_NOTIFY_MAILS)); $sender->MailMsg({to => $arg_ref->{to}, subject => $arg_ref->{subject}, encoding => "Quoted-printable", ## read this from paramete +rs? msg => encode($charset,$arg_ref->{msg}), }); if (defined $sender->{'error'} ){ logerror( "Error sending mail to $arg_ref->{to}: Error code $sende +r->{'error'} ($sender->{'error_msg'})"); $sendfailed = 1; } } } # if ($sender > 0) else { logerror("Could not establish mail sender to $arg_ref->{to}: Error + code $sender ($Mail::Sender::Error)"); $sendfailed = 1; } return ($sendfailed) ? 0 : 1; }

When it failed this morning the last lines sent to the terminal window were:

Running MailChangeNotifications Running sendmail() $sender created OK sending mail without attachment

I realized when composing this post that my diagnostics do not log the successful exit of MailMsg, and I have modified my production code to do so in future, but I believe I am justified in suspecting MailMsg because:

Thanks in advance to anyone who can help...