src/lib/errCatch.c 1.4
1.4 2009/11/03 00:35:53 angie
Make errCatch POSIX thread (pthread) safe: instead of a single global stack, use per-thread stacks hashed by thread ID.
Index: src/lib/errCatch.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/lib/errCatch.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -b -B -U 4 -r1.3 -r1.4
--- src/lib/errCatch.c 12 Aug 2009 18:13:19 -0000 1.3
+++ src/lib/errCatch.c 3 Nov 2009 00:35:53 -0000 1.4
@@ -16,8 +16,10 @@
#include "common.h"
#include "errabort.h"
#include "dystring.h"
+#include "hash.h"
+#include <pthread.h>
#include "errCatch.h"
static char const rcsid[] = "$Id$";
@@ -41,20 +43,38 @@
freez(pErrCatch);
}
}
-static struct errCatch *errCatchStack = NULL;
+static struct errCatch **getStack()
+/* Return a pointer to the errCatch object stack for the current pthread. */
+{
+static struct hash *perThreadStacks = NULL;
+int pid = pthread_self();
+// A true integer has function would be nicer, but this will do.
+// Don't safef, theoretically that could abort.
+char key[16];
+snprintf(key, sizeof(key), "%d", pid);
+key[ArraySize(key)-1] = '\0';
+if (perThreadStacks == NULL)
+ perThreadStacks = hashNew(0);
+struct hashEl *hel = hashLookup(perThreadStacks, key);
+if (hel == NULL)
+ hel = hashAdd(perThreadStacks, key, NULL);
+return (struct errCatch **)(&hel->val);
+}
static void errCatchAbortHandler()
/* semiAbort */
{
+struct errCatch **pErrCatchStack = getStack(), *errCatchStack = *pErrCatchStack;
errCatchStack->gotError = TRUE;
longjmp(errCatchStack->jmpBuf, -1);
}
static void errCatchWarnHandler(char *format, va_list args)
/* Write an error to top of errCatchStack. */
{
+struct errCatch **pErrCatchStack = getStack(), *errCatchStack = *pErrCatchStack;
dyStringVaPrintf(errCatchStack->message, format, args);
dyStringAppendC(errCatchStack->message, '\n');
}
@@ -62,20 +82,22 @@
/* Push error handlers. Not usually called directly. */
{
pushAbortHandler(errCatchAbortHandler);
pushWarnHandler(errCatchWarnHandler);
-slAddHead(&errCatchStack, errCatch);
+struct errCatch **pErrCatchStack = getStack();
+slAddHead(pErrCatchStack, errCatch);
return TRUE;
}
void errCatchEnd(struct errCatch *errCatch)
/* Restore error handlers and pop self off of catching stack. */
{
popWarnHandler();
popAbortHandler();
+struct errCatch **pErrCatchStack = getStack(), *errCatchStack = *pErrCatchStack;
if (errCatch != errCatchStack)
errAbort("Mismatch betweene errCatch and errCatchStack");
-errCatchStack = errCatch->next;
+*pErrCatchStack = errCatch->next;
}
boolean errCatchFinish(struct errCatch **pErrCatch)
/* Finish up error catching. Report error if there is a