[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

Re: ra_serf infinite loop with mod_ssl and mod_deflate

From: Philip Martin <philip_at_codematters.co.uk>
Date: Tue, 11 Nov 2014 12:49:48 +0000

Philip Martin <philip.martin_at_wandisco.com> writes:

> handle_fetch (request=0x7ffff3e56038, response=0x7ffff3e918b8,
> handler_baton=0x7ffff3e611e0, pool=0x7ffff3e6d028)
> at ../src/subversion/libsvn_ra_serf/update.c:1152
> 1152 if (SERF_BUCKET_READ_ERROR(status))
> (gdb) p status
> $13 = 0

So that's what happens when I interrupt the infinite loop, i.e. long
after the first failure to read from the socket. If I catch the first
socket read error then serf does supply an error to ra_serf:

(gdb)
serf_dechunk_read (bucket=0x7ffff3e92338, requested=8096, data=0x7fffffffd308,
    len=0x7fffffffd300) at buckets/dechunk_buckets.c:126
126 if (SERF_BUCKET_READ_ERROR(status))
(gdb) n
132 ctx->body_left -= *len;
(gdb)
133 if (!ctx->body_left) {
(gdb)
139 if (ctx->body_left && APR_STATUS_IS_EOF(status)) {
(gdb)
140 return SERF_ERROR_TRUNCATED_HTTP_RESPONSE;
(gdb)
184 }
(gdb)
serf_deflate_read (bucket=0x7ffff3e924b8, requested=8000, data=0x7fffffffd430,
    len=0x7fffffffd428) at buckets/deflate_buckets.c:260
260 if (SERF_BUCKET_READ_ERROR(ctx->stream_status)) {
(gdb)
261 return ctx->stream_status;
(gdb) p ctx->stream_status
$5 = 120106
(gdb) n
388 }
(gdb)
serf_response_read (bucket=0x7ffff3e918b8, requested=8000,
    data=0x7fffffffd430, len=0x7fffffffd428) at buckets/response_buckets.c:412
412 if (SERF_BUCKET_READ_ERROR(rv))
(gdb)
413 return rv;
(gdb) p rv
$6 = 120106
(gdb) n
425 }

So serf returned SERF_ERROR_TRUNCATED_HTTP_RESPONSE to ra_serf which
responds by converting it to APR_EAGAIN:

(gdb)
handle_fetch (request=0x7ffff3e56038, response=0x7ffff3e918b8,
    handler_baton=0x7ffff3e611e0, pool=0x7ffff3e6d028)
    at ../src/subversion/libsvn_ra_serf/update.c:1152
1152 if (SERF_BUCKET_READ_ERROR(status))
(gdb)
1154 return svn_ra_serf__wrap_err(status, NULL);
(gdb)
1221 }
(gdb)
handle_response (request=0x7ffff3e56038, response=0x7ffff3e918b8,
    handler=0x7ffff3e61220, serf_status=0x7fffffffd57c,
    scratch_pool=0x7ffff3e6d028)
    at ../src/subversion/libsvn_ra_serf/util.c:1391
1391 if (err

(gdb) p err->apr_err
$7 = 120106
(gdb)
handle_response_cb (request=0x7ffff3e56038, response=0x7ffff3e918b8,
    baton=0x7ffff3e61220, scratch_pool=0x7ffff3e6d028)
    at ../src/subversion/libsvn_ra_serf/util.c:1425
1425 outer_status = save_error(handler->session, err);
(gdb)
1426 if (!outer_status)
(gdb) p outer_status
$9 = 120106
(gdb) n
1430 if (APR_STATUS_IS_EOF(outer_status) || APR_STATUS_IS_EOF(inner_status))
(gdb) n
1443 else if (SERF_BUCKET_READ_ERROR(outer_status)
(gdb)
1444 && handler->session->pending_error)
(gdb)
1446 handler->discard_body = TRUE; /* Discard further data */
(gdb)
1447 handler->done = TRUE; /* Mark as done */
(gdb)
1448 handler->scheduled = FALSE;
(gdb)
1449 outer_status = APR_EAGAIN; /* Exit context loop */
(gdb)
1452 return outer_status;

So ra_serf hands back APR_EAGAIN to serf which responds by converting it
to APR_SUCCESS:

read_from_connection (conn=0x7ffff3e73028) at outgoing.c:1131
1131 if (APR_STATUS_IS_ECONNRESET(status) ||
(gdb)
1132 APR_STATUS_IS_ECONNABORTED(status) ||
(gdb)
1150 if (APR_STATUS_IS_EAGAIN(status)) {
(gdb)
1155 if (request_or_data_pending(&request, conn) && !request) {
(gdb)
1159 status = APR_SUCCESS;
(gdb)
1232 apr_pool_destroy(tmppool);
(gdb)
1233 return status;

-- 
Philip
Received on 2014-11-11 13:50:22 CET

This is an archived mail posted to the Subversion Dev mailing list.