Trying to update my working copy I observed svn spinning on the CPU
forever. Attaching with gdb showed that it was stuck in an endless
loop inside svn_ra_serf__handle_xml_parser().
Below is the code. The problem was that serf_bucket_read() returned
zero bytes but also indicated success. If that happens the loop never
terminates.
I suppose this code was written with the assumption that reading
from the socket would always block until data is available?
This does not seem to happen in my case. Maybe serf is doing something
wrong when it opens the socket?
I'm using serf-0.7.x from the branch as of June 21.
while (1)
{
const char *data;
apr_size_t len;
status = serf_bucket_read(response, PARSE_CHUNK_SIZE, &data, &len);
if (SERF_BUCKET_READ_ERROR(status))
{
return svn_error_wrap_apr(status, NULL);
}
/* Note: once the callbacks invoked by inject_to_parser() sets the
PAUSED flag, then it will not be cleared. write_to_pending() will
only save the content. Logic outside of serf_context_run() will
clear that flag, as appropriate, along with processing the
content that we have placed into the PENDING buffer.
We want to save arriving content into the PENDING structures if
the parser has been paused, or we already have data in there (so
the arriving data is appended, rather than injected out of order) */
#ifdef DISABLE_THIS_FOR_NOW
if (ctx->paused || HAS_PENDING_DATA(ctx->pending))
{
err = write_to_pending(ctx, data, len, pool);
}
else
#endif
{
err = inject_to_parser(ctx, data, len, &sl);
if (err)
{
/* Should have no errors if IGNORE_ERRORS is set. */
SVN_ERR_ASSERT(!ctx->ignore_errors);
}
}
if (err)
{
XML_ParserFree(ctx->xmlp);
add_done_item(ctx);
return svn_error_return(err);
}
if (APR_STATUS_IS_EAGAIN(status))
{
return svn_error_wrap_apr(status, NULL);
}
if (APR_STATUS_IS_EOF(status))
{
if (ctx->pending != NULL)
ctx->pending->network_eof = TRUE;
/* We just hit the end of the network content. If we have nothing
in the PENDING structures, then we're completely done. */
if (!HAS_PENDING_DATA(ctx->pending))
{
/* Ignore the return status. We just don't care. */
(void) XML_Parse(ctx->xmlp, NULL, 0, 1);
XML_ParserFree(ctx->xmlp);
add_done_item(ctx);
}
return svn_error_wrap_apr(status, NULL);
}
/* feed me! */
}
Received on 2011-06-24 14:45:21 CEST