aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/ecpg/ecpglib/misc.c41
1 files changed, 30 insertions, 11 deletions
diff --git a/src/interfaces/ecpg/ecpglib/misc.c b/src/interfaces/ecpg/ecpglib/misc.c
index 79aa34c7fa5..4b54322926d 100644
--- a/src/interfaces/ecpg/ecpglib/misc.c
+++ b/src/interfaces/ecpg/ecpglib/misc.c
@@ -91,7 +91,7 @@ static struct sqlca_t sqlca =
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t debug_init_mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
-static int simple_debug = 0;
+static volatile int simple_debug = 0;
static FILE *debugstream = NULL;
void
@@ -241,7 +241,11 @@ void
ECPGdebug(int n, FILE *dbgs)
{
#ifdef ENABLE_THREAD_SAFETY
+ /* Interlock against concurrent executions of ECPGdebug() */
pthread_mutex_lock(&debug_init_mutex);
+
+ /* Prevent ecpg_log() from printing while we change settings */
+ pthread_mutex_lock(&debug_mutex);
#endif
if (n > 100)
@@ -254,6 +258,12 @@ ECPGdebug(int n, FILE *dbgs)
debugstream = dbgs;
+ /* We must release debug_mutex before invoking ecpg_log() ... */
+#ifdef ENABLE_THREAD_SAFETY
+ pthread_mutex_unlock(&debug_mutex);
+#endif
+
+ /* ... but keep holding debug_init_mutex to avoid racy printout */
ecpg_log("ECPGdebug: set to %d\n", simple_debug);
#ifdef ENABLE_THREAD_SAFETY
@@ -270,6 +280,11 @@ ecpg_log(const char *format,...)
int bufsize;
char *fmt;
+ /*
+ * For performance reasons, inspect simple_debug without taking the mutex.
+ * This could be problematic if fetching an int isn't atomic, but we
+ * assume that it is in many other places too.
+ */
if (!simple_debug)
return;
@@ -294,18 +309,22 @@ ecpg_log(const char *format,...)
pthread_mutex_lock(&debug_mutex);
#endif
- va_start(ap, format);
- vfprintf(debugstream, fmt, ap);
- va_end(ap);
-
- /* dump out internal sqlca variables */
- if (ecpg_internal_regression_mode && sqlca != NULL)
+ /* Now that we hold the mutex, recheck simple_debug */
+ if (simple_debug)
{
- fprintf(debugstream, "[NO_PID]: sqlca: code: %ld, state: %s\n",
- sqlca->sqlcode, sqlca->sqlstate);
- }
+ va_start(ap, format);
+ vfprintf(debugstream, fmt, ap);
+ va_end(ap);
- fflush(debugstream);
+ /* dump out internal sqlca variables */
+ if (ecpg_internal_regression_mode && sqlca != NULL)
+ {
+ fprintf(debugstream, "[NO_PID]: sqlca: code: %ld, state: %s\n",
+ sqlca->sqlcode, sqlca->sqlstate);
+ }
+
+ fflush(debugstream);
+ }
#ifdef ENABLE_THREAD_SAFETY
pthread_mutex_unlock(&debug_mutex);