summaryrefslogtreecommitdiff
path: root/rts/eventlog
diff options
context:
space:
mode:
authorBen Gamari <ben@smart-cactus.org>2020-05-21 11:53:35 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2020-05-27 00:14:33 -0400
commit04750304deae2128a8350e28224e1f62ae949820 (patch)
tree2b2f402defb7aa7ede3a75dc05b724b32adc381f /rts/eventlog
parentede241268171e8eee1e750d88ff356ddbfc357f2 (diff)
downloadhaskell-04750304deae2128a8350e28224e1f62ae949820.tar.gz
eventlog: Fix racy flushing
Previously no attempt was made to avoid multiple threads writing their capability-local eventlog buffers to the eventlog writer simultaneously. This could result in multiple eventlog streams being interleaved. Fix this by documenting that the EventLogWriter's write() and flush() functions may be called reentrantly and fix the default writer to protect its FILE* by a mutex. Fixes #18210.
Diffstat (limited to 'rts/eventlog')
-rw-r--r--rts/eventlog/EventLogWriter.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/rts/eventlog/EventLogWriter.c b/rts/eventlog/EventLogWriter.c
index b19e617a4c..5387f932eb 100644
--- a/rts/eventlog/EventLogWriter.c
+++ b/rts/eventlog/EventLogWriter.c
@@ -28,6 +28,17 @@ static pid_t event_log_pid = -1;
// File for logging events
static FILE *event_log_file = NULL;
+#if defined(THREADED_RTS)
+// Protects event_log_file
+static Mutex event_log_mutex;
+
+static void acquire_event_log_lock(void) { ACQUIRE_LOCK(&event_log_mutex); }
+static void release_event_log_lock(void) { RELEASE_LOCK(&event_log_mutex); }
+#else
+static void acquire_event_log_lock(void) {}
+static void release_event_log_lock(void) {}
+#endif
+
static void initEventLogFileWriter(void);
static bool writeEventLogFile(void *eventlog, size_t eventlog_size);
static void flushEventLogFile(void);
@@ -89,6 +100,9 @@ initEventLogFileWriter(void)
}
stgFree(event_log_filename);
+#if defined(THREADED_RTS)
+ initMutex(&event_log_mutex);
+#endif
}
static bool
@@ -97,15 +111,17 @@ writeEventLogFile(void *eventlog, size_t eventlog_size)
unsigned char *begin = eventlog;
size_t remain = eventlog_size;
+ acquire_event_log_lock();
while (remain > 0) {
size_t written = fwrite(begin, 1, remain, event_log_file);
if (written == 0) {
+ release_event_log_lock();
return false;
}
remain -= written;
begin += written;
}
-
+ release_event_log_lock();
return true;
}
@@ -124,6 +140,9 @@ stopEventLogFileWriter(void)
fclose(event_log_file);
event_log_file = NULL;
}
+#if defined(THREADED_RTS)
+ closeMutex(&event_log_mutex);
+#endif
}
const EventLogWriter FileEventLogWriter = {