Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Net-HTTP 6.06 intermittent death in Net::HTTP::Methods sub my_readline() (solved) [rt.cpan.org #86448] #28

Open
oalders opened this issue Mar 30, 2017 · 0 comments

Comments

@oalders
Copy link
Member

oalders commented Mar 30, 2017

Migrated from rt.cpan.org#86448 (status was 'new')

Requestors:

From [email protected] on 2013-06-26 15:46:52:

Description:

Net::HTTP::Methods from Net-HTTP 6.06 dies intermittently with:

Status read failed: No such file or directory at �/perl/vendor/lib/Net/HTTP/Methods.pm line 265.


Cause:

IO::Socket::SSL object can reject the read request with an error of either "SSL wants a read first" or "SSL wants a write first."  This is apparently some overhead of SSL where it wants a read/write before allowing you to read/write in some cases.  It's described somewhat (but not much) better under errstr() in the latest IO::Socket::SSL perldoc.


Reproducing:

I'm not sure how hard this is to reproduce since triggers are unknown.  I'm accessing cloud based SOAP via SOAP::WSDL over https from a busy server and it occurs maybe one out of a dozen times.  It seems to correlate with SSL taking an extra bit of time to setup the connection when something in the chain is busier or has a little latency.  Thus far, I've only seen SSL_WANT_READ, and it clears immediately on the next redo READ, but there seems to be no harm in preparing for SSL_WANT_WRITE in the patch as well.


Patch:

--- broken/Net/HTTP/Methods.pm    2013-03-10 23:35:42.000000000 -0500
+++ fixed/Net/HTTP/Methods.pm 2013-06-26 10:12:37.205639200 -0500
@@ -243,40 +243,41 @@
 sub my_readline {
     my $self = shift;
     my $what = shift;
     for (${*$self}{'http_buf'}) {
        my $max_line_length = ${*$self}{'http_max_line_length'};
        my $pos;
        while (1) {
            # find line ending
            $pos = index($_, "\012");
            last if $pos >= 0;
            die "$what line too long (limit is $max_line_length)"
                if $max_line_length && length($_) > $max_line_length;

            # need to read more data to find a line ending
           READ:
             {
                 die "read timeout" unless $self->can_read;
                 my $n = $self->sysread($_, 1024, length);
                 unless (defined $n) {
                     redo READ if $!{EINTR} || $!{EAGAIN};
+                    redo READ if ( $self->isa('IO::Socket::SSL') && $self->errstr() =~ /^SSL wants a (?:read|write) first$/ );
                     # if we have already accumulated some data let's at least
                     # return that as a line
                     die "$what read failed: $!" unless length;
                 }
                 unless ($n) {
                     return undef unless length;
                     return substr($_, 0, length, "");
                 }
             }
        }
        die "$what line too long ($pos; limit is $max_line_length)"
            if $max_line_length && $pos > $max_line_length;

        my $line = substr($_, 0, $pos+1, "");
        $line =~ s/(\015?\012)\z// || die "Assert";
        return wantarray ? ($line, $1) : $line;
     }
 }


Thanks for your time and your code.

--

Raymond Ferguson

Integrated Applications Engineer  | CDW

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant