Changeset 4261999 in mod_gnutls


Ignore:
Timestamp:
Jan 28, 2015, 5:51:36 PM (8 years ago)
Author:
Thomas Klute <thomas2.klute@…>
Branches:
asyncio, debian/master, debian/stretch-backports, jessie-backports, main, master, proxy-ticket, upstream
Children:
265eafc
Parents:
398d1a0
Message:

gnutls_io_input_read: Retry gnutls_record_recv if necessary

While testing TLS proxy back end connection, requests occasionally
failed (empty response) with strange log messages like these:

[http:info] [pid 17004:tid 140701602649856] (20014)Internal error: [remote A.B.C.D:443] AH01590: Error reading chunk
[proxy_http:error] [pid 17004:tid 140701602649856] (28)No space left on device: [client A.B.C.E:36002] AH01110: error reading response

Investigation of the Apache source code (in particular mod_proxy_http
and the default http filter) indicated that these were the results of
APR_EGENERAL errors returned from the mod_gnutls input filter
(mgs_filter_input) while receiving the response from the back end
server.

The reason behind these errors was that gnutls_io_input_read (called
directly or through gnutls_io_input_getline) did not handle
interruptions of the GnuTLS receive function gnutls_record_recv
properly. The GnuTLS documentation states that "If GNUTLS_E_INTERRUPTED
or GNUTLS_E_AGAIN is returned, you must call this function again to get
the data." Adding a retry loop like the ones already used for some other
GnuTLS library calls in gnutls_io.c around the gnutls_record_recv call
solved the problem.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/gnutls_io.c

    r398d1a0 r4261999  
    231231    while (1) {
    232232
    233         rc = gnutls_record_recv(ctxt->session, buf + bytes,
    234                 wanted - bytes);
     233        do
     234            rc = gnutls_record_recv(ctxt->session, buf + bytes,
     235                                    wanted - bytes);
     236        while (rc == GNUTLS_E_INTERRUPTED || rc == GNUTLS_E_AGAIN);
    235237
    236238        if (rc > 0) {
     
    312314
    313315            if (ctxt->input_rc == APR_SUCCESS) {
     316                ap_log_cerror(APLOG_MARK, APLOG_INFO, ctxt->input_rc, ctxt->c,
     317                              "%s: GnuTLS error: %s (%d)",
     318                              __func__, gnutls_strerror(rc), rc);
    314319                ctxt->input_rc = APR_EGENERAL;
    315320            }
Note: See TracChangeset for help on using the changeset viewer.