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

serf infinite loop in svn_ra_serf__handle_xml_parser()

From: Stefan Sperling <stsp_at_elego.de>
Date: Fri, 24 Jun 2011 14:44:45 +0200

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

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

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.