diff --git a/src/backend/lib/stringinfo.c b/src/backend/lib/stringinfo.c
index a5b9f2e..2de6bbf 100644
--- a/src/backend/lib/stringinfo.c
+++ b/src/backend/lib/stringinfo.c
@@ -80,18 +80,28 @@ appendStringInfo(StringInfo str, const char *fmt,...)
 	for (;;)
 	{
 		va_list		args;
-		bool		success;
+		int			needed;
 
 		/* Try to format the data. */
 		va_start(args, fmt);
-		success = appendStringInfoVA(str, fmt, args);
+		needed = appendStringInfoVA(str, fmt, args);
 		va_end(args);
 
-		if (success)
+		if (!needed)
 			break;
 
-		/* Double the buffer size and try again. */
-		enlargeStringInfo(str, str->maxlen);
+		/* maintain growth in multiples of 2 */
+		if (needed > str->maxlen)
+		{
+			int newsize = str->maxlen;
+			while (newsize < needed)
+				newsize *= 2;
+			needed = newsize;
+		}
+		else
+			needed = str->maxlen;
+
+		enlargeStringInfo(str, needed);
 	}
 }
 
@@ -100,16 +110,20 @@ appendStringInfo(StringInfo str, const char *fmt,...)
  *
  * Attempt to format text data under the control of fmt (an sprintf-style
  * format string) and append it to whatever is already in str.	If successful
- * return true; if not (because there's not enough space), return false
- * without modifying str.  Typically the caller would enlarge str and retry
- * on false return --- see appendStringInfo for standard usage pattern.
- *
+ * return 0; if not (because there's not enough space), return a positive
+ * number. This number is the return value of the call to vsnprintf. 
+ * Implementations of vsnprintf vary and this value may NOT be the length
+ * required for the whole string, so callers should take this value with a
+ * pinch of salt and treat the value returned as a hint that the space 
+ * required might be bigger than they would think.
+ * --- see appendStringInfo for standard usage pattern.
+ * 
  * XXX This API is ugly, but there seems no alternative given the C spec's
  * restrictions on what can portably be done with va_list arguments: you have
  * to redo va_start before you can rescan the argument list, and we can't do
  * that from here.
  */
-bool
+int
 appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
 {
 	int			avail,
@@ -123,7 +137,7 @@ appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
 	 */
 	avail = str->maxlen - str->len - 1;
 	if (avail < 16)
-		return false;
+		return 1; /* 1 will do as we don't know how much space is needed */
 
 	/*
 	 * Assert check here is to catch buggy vsnprintf that overruns the
@@ -147,12 +161,12 @@ appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
 	{
 		/* Success.  Note nprinted does not include trailing null. */
 		str->len += nprinted;
-		return true;
+		return 0;
 	}
 
 	/* Restore the trailing null so that str is unmodified. */
 	str->data[str->len] = '\0';
-	return false;
+	return nprinted < 0 ? 1 : nprinted + 1;
 }
 
 /*
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 9c7489a..319af01 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -714,12 +714,12 @@ errcode_for_socket_access(void)
 		/* Generate actual output --- have to use appendStringInfoVA */ \
 		for (;;) \
 		{ \
-			va_list		args; \
-			bool		success; \
+			va_list	args; \
+			int		needed; \
 			va_start(args, fmt); \
-			success = appendStringInfoVA(&buf, fmtbuf, args); \
+			needed = appendStringInfoVA(&buf, fmtbuf, args); \
 			va_end(args); \
-			if (success) \
+			if (!needed) \
 				break; \
 			enlargeStringInfo(&buf, buf.maxlen); \
 		} \
@@ -757,12 +757,12 @@ errcode_for_socket_access(void)
 		/* Generate actual output --- have to use appendStringInfoVA */ \
 		for (;;) \
 		{ \
-			va_list		args; \
-			bool		success; \
+			va_list	args; \
+			int		needed; \
 			va_start(args, n); \
-			success = appendStringInfoVA(&buf, fmtbuf, args); \
+			needed = appendStringInfoVA(&buf, fmtbuf, args); \
 			va_end(args); \
-			if (success) \
+			if (!needed) \
 				break; \
 			enlargeStringInfo(&buf, buf.maxlen); \
 		} \
diff --git a/src/include/lib/stringinfo.h b/src/include/lib/stringinfo.h
index ecb693f..f6b14ac 100644
--- a/src/include/lib/stringinfo.h
+++ b/src/include/lib/stringinfo.h
@@ -97,15 +97,20 @@ appendStringInfo(StringInfo str, const char *fmt,...)
 /* This extension allows gcc to check the format string */
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 3)));
 
-/*------------------------
+ /*------------------------
  * appendStringInfoVA
+ *
  * Attempt to format text data under the control of fmt (an sprintf-style
  * format string) and append it to whatever is already in str.	If successful
- * return true; if not (because there's not enough space), return false
- * without modifying str.  Typically the caller would enlarge str and retry
- * on false return --- see appendStringInfo for standard usage pattern.
+ * return 0; if not (because there's not enough space), return a positive
+ * number. This number is the return value of the call to vsnprintf. 
+ * Implementations of vsnprintf vary and this value may NOT be the length
+ * required for the whole string, so callers should take this value with a
+ * pinch of salt and treat the value returned as a hint that the space 
+ * required might be bigger than they would think.
+ * --- see appendStringInfo for standard usage pattern.
  */
-extern bool
+extern int
 appendStringInfoVA(StringInfo str, const char *fmt, va_list args)
 __attribute__((format(PG_PRINTF_ATTRIBUTE, 2, 0)));
 
