Philip Martin <phi...@codematters.co.uk> writes:

> Philip Martin <philip.mar...@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:

I can reproduce over plain HTTP without mod_ssl -

  - the closed socket causes apr_socket_recv() to returns APR_EOF
  - APR_EOF gets returned to serf_deflate_read()
  - APR_EOF gets stored in deflate_context_t->stream_status
  - serf_deflate_read() returns APR_SUCCESS
  - serf_response_read() returns APR_SUCCESS

The ra_serf infinite loop is calling serf_response_read() which calls
serf_deflate_read() which keeps converting APR_EOF into APR_SUCCESS:

serf_deflate_read (bucket=0x7ffff3e8f4b8, requested=8000, data=0x7fffffffd460, 
    len=0x7fffffffd458) at buckets/deflate_buckets.c:143
143         deflate_context_t *ctx = bucket->data;
(gdb) n
150             switch (ctx->state) {
(gdb) p ctx->stream_status
$24 = 70014
(gdb) n
224                 status = serf_bucket_read(ctx->inflate_stream, requested, 
data,
(gdb) 
226                 if (SERF_BUCKET_READ_ERROR(status)) {
(gdb) 
230                 if (APR_STATUS_IS_EOF(status)) {
(gdb) 
231                     status = ctx->stream_status;
(gdb) 
232                     if (APR_STATUS_IS_EOF(status)) {
(gdb) 
237                         status = APR_SUCCESS;
(gdb) 
240                 if (*len != 0) {
(gdb) 
251                 if (ctx->zstream.avail_in == 0) {
(gdb) 
255                     ctx->stream_status = serf_bucket_read(ctx->stream,
(gdb) 
260                     if (SERF_BUCKET_READ_ERROR(ctx->stream_status)) {
(gdb) 
264                     if (!private_len && 
APR_STATUS_IS_EAGAIN(ctx->stream_status)) {
(gdb) 
271                     ctx->zstream.next_in = (unsigned char*)private_data;
(gdb) 
272                     ctx->zstream.avail_in = private_len;
(gdb) 
277                     zRC = inflate(&ctx->zstream, Z_NO_FLUSH);
(gdb) 
281                     if (zRC == Z_BUF_ERROR || ctx->zstream.avail_out == 0) {
(gdb) 
283                         ctx->zstream.next_out = ctx->buffer;
(gdb) 
284                         private_len = ctx->bufferSize - 
ctx->zstream.avail_out;
(gdb) 
286                         ctx->crc = crc32(ctx->crc, (const Bytef 
*)ctx->buffer,
(gdb) 
290                         tmp = SERF_BUCKET_SIMPLE_STRING_LEN((char 
*)ctx->buffer,
(gdb) 
293                         serf_bucket_aggregate_append(ctx->inflate_stream, 
tmp);
(gdb) 
294                         ctx->zstream.avail_out = ctx->bufferSize;
(gdb) 
295                         break;
(gdb) 
352                 status = serf_bucket_read(ctx->inflate_stream, requested, 
data,
(gdb) 
355                 if (APR_STATUS_IS_EOF(status)) {
(gdb) p status
$25 = 70014
(gdb) n
356                     status = ctx->stream_status;
(gdb) 
359                     if (zRC != Z_STREAM_END)
(gdb) 
360                         return APR_SUCCESS;


-- 
Philip Martin | Subversion Committer
WANdisco // *Non-Stop Data*
serf

Reply via email to