7220331d99c960562d2dbd5b293bf0002827043a
max
  Sat May 16 08:06:42 2015 -0700
add a hg.conf option that makes sure that errAbort messages are always
shown to the user, even when they are before a Content-type, refs #15332

diff --git src/lib/errAbort.c src/lib/errAbort.c
index 961fe56..860bcab 100644
--- src/lib/errAbort.c
+++ src/lib/errAbort.c
@@ -16,53 +16,65 @@
  * granted for all use - public, private or commercial. */
 
 // developer: this include is for an occasionally useful means of getting stack info without
 // crashing
 // however, it is not supported on cygwin.  Conditionally compile this in when desired.
 //#define BACKTRACE_EXISTS
 #ifdef BACKTRACE_EXISTS
 #include <execinfo.h>
 #endif///def BACKTRACE_EXISTS
 #include <pthread.h>
 #include "common.h"
 #include "hash.h"
 #include "dystring.h"
 #include "errAbort.h"
 
-
+// errAbort can optionally print a Content-type line and copy errors to stdout, so 
+// error messages don't lead to a 500 error but are shown in the web browser
+// directly. 
+static boolean doContentType = FALSE;
 
 #define maxWarnHandlers 20
 #define maxAbortHandlers 12
 struct perThreadAbortVars
 /* per thread variables for abort and warn */
     {
     boolean debugPushPopErr;        // generate stack dump on push/pop error
     boolean errAbortInProgress;     /* Flag to indicate that an error abort is in progress.
                                       * Needed so that a warn handler can tell if it's really
                                       * being called because of a warning or an error. */
     WarnHandler warnArray[maxWarnHandlers];
     int warnIx;
     AbortHandler abortArray[maxAbortHandlers];
     int abortIx;
     };
 
 static struct perThreadAbortVars *getThreadVars();  // forward declaration
 
 static void defaultVaWarn(char *format, va_list args)
 /* Default error message handler. */
 {
 if (format != NULL) {
+    if (doContentType)
+        {
+        puts("Content-type: text/html\n");
+        puts("Error: ");
+        vfprintf(stdout, format, args);
+        fprintf(stdout, "\n");
+        fflush(stdout);
+        }
+
     fflush(stdout);
     vfprintf(stderr, format, args);
     fprintf(stderr, "\n");
     fflush(stderr);
     }
 }
 
 static void silentVaWarn(char *format, va_list args)
 /* Warning handler that just hides it.  Useful sometimes when high level code
  * expects low level code may fail (as in finding a file on the net) but doesn't
  * want user to be bothered about it. */
 {
 }
 
 
@@ -188,30 +200,37 @@
 
 void vaErrAbort(char *format, va_list args)
 /* Abort function, with optional (vprintf formatted) error message. */
 {
 /* flag is needed because both errAbort and warn generate message
  * using the warn handler, however sometimes one needed to know
  * (like when logging), if it's an error or a warning.  This is far from
  * perfect, as this isn't cleared if the error handler continues,
  * as with an exception mechanism. */
 struct perThreadAbortVars *ptav = getThreadVars();
 ptav->errAbortInProgress = TRUE;
 vaWarn(format, args);
 noWarnAbort();
 }
 
+void errAbortSetDoContentType(boolean value)
+/* change the setting of doContentType, ie. if errorAbort should print a 
+ * http Content type line. */
+{
+doContentType = value;
+}
+
 void errAbort(char *format, ...)
 /* Abort function, with optional (printf formatted) error message. */
 {
 #ifdef COREDUMP
     abort();
 #endif
 va_list args;
 va_start(args, format);
 vaErrAbort(format, args);
 va_end(args);
 }
 
 void errnoAbort(char *format, ...)
 /* Prints error message from UNIX errno first, then does errAbort. */
 {