Changeset bd2b48b in mod_gnutls for src/gnutls_io.c


Ignore:
Timestamp:
Sep 30, 2018, 1:20:53 PM (2 years ago)
Author:
Fiona Klute <fiona.klute@…>
Branches:
debian/master, master, proxy-ticket
Children:
fdd3bf0
Parents:
78d75ac
Message:

Immediately retry on EINTR or EAGAIN for blocking receive

Proxy TLS connections failed with EAGAIN in tests while trying to read
the response header if the server sent a large ticket, presumably
because records had to wait for the ticket to be passed. This fixes
the issue.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_io.c

    r78d75ac rbd2b48b  
    242242    while (1)
    243243    {
     244        /* Note: The pull function sets ctxt->input_rc */
    244245        rc = gnutls_record_recv(ctxt->session, buf + bytes, wanted - bytes);
    245 
    246         if (rc == GNUTLS_E_INTERRUPTED)
    247             ctxt->input_rc = APR_EINTR;
    248         else if (rc == GNUTLS_E_AGAIN)
    249             ctxt->input_rc = APR_EAGAIN;
    250246
    251247        if (rc > 0) {
     
    258254            return ctxt->input_rc;
    259255        } else if (rc == 0) {
    260             /* If EAGAIN, we will loop given a blocking read,
    261              * otherwise consider ourselves at EOF.
    262              */
    263             if (APR_STATUS_IS_EAGAIN(ctxt->input_rc)
    264                     || APR_STATUS_IS_EINTR(ctxt->input_rc)) {
    265                 /* Already read something, return APR_SUCCESS instead.
    266                  * On win32 in particular, but perhaps on other kernels,
    267                  * a blocking call isn't 'always' blocking.
    268                  */
    269                 if (*len > 0) {
    270                     ctxt->input_rc = APR_SUCCESS;
    271                     break;
    272                 }
    273                 if (ctxt->input_block == APR_NONBLOCK_READ) {
    274                     break;
    275                 }
     256            /* EOF, return code depends on whether we still have data
     257             * to return. */
     258            if (*len > 0) {
     259                ctxt->input_rc = APR_SUCCESS;
    276260            } else {
    277                 if (*len > 0) {
    278                     ctxt->input_rc = APR_SUCCESS;
    279                 } else {
    280                     ctxt->input_rc = APR_EOF;
    281                 }
    282                 break;
    283             }
     261                ctxt->input_rc = APR_EOF;
     262            }
     263            break;
    284264        } else { /* (rc < 0) */
    285265
    286             if (rc == GNUTLS_E_REHANDSHAKE) {
     266            if (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN)
     267            {
     268                ap_log_cerror(APLOG_MARK, APLOG_TRACE2, ctxt->input_rc, ctxt->c,
     269                              "%s: looping recv after '%s' (%d)",
     270                              __func__, gnutls_strerror(rc), rc);
     271                /* For a blocking read: Loop and try again immediately. */
     272                if (ctxt->input_block != APR_NONBLOCK_READ)
     273                    continue;
     274            } else if (rc == GNUTLS_E_REHANDSHAKE) {
    287275                /* A client has asked for a new Hankshake. Currently, we don't do it */
    288276                ap_log_cerror(APLOG_MARK, APLOG_INFO,
     
    881869                && APR_BRIGADE_EMPTY(ctxt->input_bb)))
    882870        {
    883             if (APR_STATUS_IS_EOF(ctxt->input_rc))
    884             {
    885                 return 0;
    886             }
    887             else
    888             {
    889                 gnutls_transport_set_errno(ctxt->session,
    890                                            EAI_APR_TO_RAW(ctxt->input_rc));
    891                 return -1;
    892             }
     871            /* Turning APR_SUCCESS into APR_EINTR isn't ideal, but
     872             * it's the best matching error code for "didn't get data,
     873             * but read didn't permanently fail either." */
     874            ctxt->input_rc = (rc != APR_SUCCESS ? rc : APR_EINTR);
     875            gnutls_transport_set_errno(ctxt->session,
     876                                       EAI_APR_TO_RAW(ctxt->input_rc));
     877            return -1;
    893878        }
    894879
Note: See TracChangeset for help on using the changeset viewer.