summaryrefslogtreecommitdiff
path: root/rts/eventlog/EventLogWriter.c
diff options
context:
space:
mode:
Diffstat (limited to 'rts/eventlog/EventLogWriter.c')
-rw-r--r--rts/eventlog/EventLogWriter.c122
1 files changed, 122 insertions, 0 deletions
diff --git a/rts/eventlog/EventLogWriter.c b/rts/eventlog/EventLogWriter.c
new file mode 100644
index 0000000000..d6db743119
--- /dev/null
+++ b/rts/eventlog/EventLogWriter.c
@@ -0,0 +1,122 @@
+/* -----------------------------------------------------------------------------
+ *
+ * (c) The GHC Team, 2008-2009
+ *
+ * Support for fast binary event logging.
+ *
+ * ---------------------------------------------------------------------------*/
+
+#include "PosixSource.h"
+#include "Rts.h"
+
+#include "RtsUtils.h"
+#include "rts/EventLogWriter.h"
+
+#include <string.h>
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+// PID of the process that writes to event_log_filename (#4512)
+static pid_t event_log_pid = -1;
+
+// File for logging events
+static FILE *event_log_file = NULL;
+
+static void initEventLogFileWriter(void);
+static bool writeEventLogFile(void *eventlog, size_t eventlog_size);
+static void flushEventLogFile(void);
+static void stopEventLogFileWriter(void);
+
+static void
+initEventLogFileWriter(void)
+{
+ char *prog, *event_log_filename;
+
+ prog = stgMallocBytes(strlen(prog_name) + 1, "initEventLogFileWriter");
+ strcpy(prog, prog_name);
+#ifdef mingw32_HOST_OS
+ // on Windows, drop the .exe suffix if there is one
+ {
+ char *suff;
+ suff = strrchr(prog,'.');
+ if (suff != NULL && !strcmp(suff,".exe")) {
+ *suff = '\0';
+ }
+ }
+#endif
+ event_log_filename = stgMallocBytes(strlen(prog)
+ + 10 /* .%d */
+ + 10 /* .eventlog */,
+ "initEventLogFileWriter");
+
+ if (event_log_pid == -1) { // #4512
+ // Single process
+ sprintf(event_log_filename, "%s.eventlog", prog);
+ event_log_pid = getpid();
+ } else {
+ // Forked process, eventlog already started by the parent
+ // before fork
+ event_log_pid = getpid();
+ // We don't have a FMT* symbol for pid_t, so we go via Word64
+ // to be sure of not losing range. It would be nicer to have a
+ // FMT* symbol or similar, though.
+ sprintf(event_log_filename, "%s.%" FMT_Word64 ".eventlog",
+ prog, (StgWord64)event_log_pid);
+ }
+ stgFree(prog);
+
+ /* Open event log file for writing. */
+ if ((event_log_file = fopen(event_log_filename, "wb")) == NULL) {
+ sysErrorBelch(
+ "initEventLogFileWriter: can't open %s", event_log_filename);
+ stg_exit(EXIT_FAILURE);
+ }
+
+ stgFree(event_log_filename);
+}
+
+static bool
+writeEventLogFile(void *eventlog, size_t eventlog_size)
+{
+ unsigned char *begin = eventlog;
+ size_t remain = eventlog_size;
+
+ while (remain > 0) {
+ size_t written = fwrite(begin, 1, remain, event_log_file);
+ if (written == 0) {
+ return false;
+ }
+ remain -= written;
+ begin += written;
+ }
+
+ return true;
+}
+
+static void
+flushEventLogFile(void)
+{
+ if (event_log_file != NULL) {
+ fflush(event_log_file);
+ }
+}
+
+static void
+stopEventLogFileWriter(void)
+{
+ if (event_log_file != NULL) {
+ fclose(event_log_file);
+ }
+}
+
+const EventLogWriter FileEventLogWriter = {
+ .initEventLogWriter = initEventLogFileWriter,
+ .writeEventLog = writeEventLogFile,
+ .flushEventLog = flushEventLogFile,
+ .stopEventLogWriter = stopEventLogFileWriter
+};