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

BUG: svn enters unkillable state, tracked down to UTF conv in locale!=C

From: Denis Vlasenko <vda.linux_at_googlemail.com>
Date: 2006-06-26 19:49:30 CEST

This one was quite puzzling and took a lot of time to track down,
so please bear with me.

The below command failed for me:

svn co svn://busybox.net/trunk/busybox

in a rather strange way: it started to eat 100% CPU
doing nothing, ctrl-C doesn't work, kill doesn't kill it too,
only kill -9. Repeatable.

After much of fprintf() insertions I found out that
it enters infinite loop here:

/* Convert SRC_LENGTH bytes of SRC_DATA in CONVSET, store the result
   in *DEST, which is allocated in POOL. */
static svn_error_t *
convert_to_stringbuf (apr_xlate_t *convset,
                      const char *src_data,
                      apr_size_t src_length,
                      svn_stringbuf_t **dest,
                      apr_pool_t *pool)
{
  apr_size_t buflen = src_length;
  apr_status_t apr_err;
  apr_size_t srclen = src_length;
  apr_size_t destlen = 0;
  char *destbuf;

  /* Initialize *DEST to an empty stringbuf. */
fprintf(stderr, "%s:%s():%d src_data='%s'\n", __FILE__, __FUNCTION__, __LINE__, src_data); //vda
  *dest = svn_stringbuf_create ("", pool);
fprintf(stderr, "%s:%s():%d\n", __FILE__, __FUNCTION__, __LINE__); //vda
  destbuf = (*dest)->data;

  /* Not only does it not make sense to convert an empty string, but
     apr-iconv is quite unreasonable about not allowing that. */
  if (src_length == 0)
    return SVN_NO_ERROR;

  do
    {
      /* A 1:2 ratio of input characters to output characters should
         be enough for most translations, and conveniently enough, if
         it isn't, we'll grow the buffer size by 2 again. */
      if (destlen == 0)
        buflen *= 2;

      /* Ensure that *DEST has sufficient storage for the translated
         result. */
fprintf(stderr, "%s:%s():%d\n", __FILE__, __FUNCTION__, __LINE__); //vda
      svn_stringbuf_ensure (*dest, buflen + 1);
fprintf(stderr, "%s:%s():%d\n", __FILE__, __FUNCTION__, __LINE__); //vda

      /* Update the destination buffer pointer to the first character
         after already-converted output. */
      destbuf = (*dest)->data + (*dest)->len;

      /* Set up state variables for xlate. */
      destlen = buflen - (*dest)->len;

      /* Attempt the conversion. */
fprintf(stderr, "%s:%s():%d src_length=%d srclen=%d destlen=%d\n", __FILE__, __FUNCTION__, __LINE__, src_length, srclen, destlen); //vda
      apr_err = apr_xlate_conv_buffer (convset,
                                       src_data + (src_length - srclen),
                                       &srclen,
                                       destbuf,
                                       &destlen);
fprintf(stderr, "%s:%s():%d: apr_err=%d srclen=%d destlen=%d\n", __FILE__, __FUNCTION__, __LINE__, apr_err, srclen, destlen); //vda

      /* Now, update the *DEST->len to track the amount of output data
         churned out so far from this loop. */
      (*dest)->len += ((buflen - (*dest)->len) - destlen);

    } while (! apr_err && srclen);

  /* If we exited the loop with an error, return the error. */
  if (apr_err)
    /* Can't use svn_error_wrap_apr here because it calls functions in
       this file, leading to infinite recursion. */
{fprintf(stderr, "%s:%s():%d\n", __FILE__, __FUNCTION__, __LINE__); //vda
    return svn_error_create (apr_err, NULL, "Can't recode string");
fprintf(stderr, "%s:%s():%d\n", __FILE__, __FUNCTION__, __LINE__); //vda
}
  /* Else, exited due to success. Trim the result buffer down to the
     right length. */
  (*dest)->data[(*dest)->len] = '\0';

  return SVN_NO_ERROR;
}

The output is:

../subversion/libsvn_subr/error.c:svn_error_wrap_apr():162
../subversion/libsvn_subr/error.c:svn_error_wrap_apr():164
../subversion/libsvn_subr/error.c:svn_error_wrap_apr():169
/.share/usr/src/subversion-1.1.3/apr/misc/unix/errorcodes.c:apr_strerror():390
../subversion/libsvn_subr/error.c:svn_error_wrap_apr():171 errbuf='.'
../subversion/libsvn_subr/utf.c:svn_utf_cstring_to_utf8():588 src='.'
../subversion/libsvn_subr/utf.c:convert_cstring():559 src='.'
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():319 src_data='.'
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():321
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=1 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=1 destlen=2
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
        ...<forever>...

I suspected that it has something to do with my locale which
is not C, and indeed, when I unset LC_xxx vars, it worked!

Environment in which it fails:

LC_ALL=ru_RU.koi8r
LC_MESSAGES=ru_RU.koi8r
LANG=ru_RU.koi8r

# locale -a
C
en_US.utf8
POSIX
ru_RU.koi8r
ru_RU.utf8

My system has glibc-2.4 installed if it is important.

Another thing which may contribute:

APR_DECLARE(char *) apr_strerror(apr_status_t statcode, char *buf,
                                 apr_size_t bufsize)
{
    if (statcode < APR_OS_START_ERROR) {
fprintf(stderr, "%s:%s():%d\n", __FILE__, __FUNCTION__, __LINE__); //vda
        return native_strerror(statcode, buf, bufsize);
    }

This thing seems to feed garbage sometimes:

../subversion/libsvn_subr/error.c:svn_error_wrap_apr():169
/.share/usr/src/subversion-1.1.3/apr/misc/unix/errorcodes.c:apr_strerror():390
../subversion/libsvn_subr/error.c:svn_error_wrap_apr():171 errbuf='x駰C
^H.C
^H\X'
../subversion/libsvn_subr/utf.c:svn_utf_cstring_to_utf8():588 src='x駰C
^H.C
^H\X'
../subversion/libsvn_subr/utf.c:convert_cstring():559 src='x駰C
^H.C
^H\X'
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():319 src_data='x駰C
^H.C
^H\X'
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():321
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():339
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():341
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():351 src_length=16 srclen=16 destlen=32
../subversion/libsvn_subr/utf.c:convert_to_stringbuf():357: apr_err=0 srclen=0 destlen=5

Or is this UTF16?

--
vda
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org
Received on Tue Jun 27 14:39:53 2006

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