summaryrefslogtreecommitdiff
path: root/rts/eventlog
diff options
context:
space:
mode:
authoralexbiehl <alex.biehl@gmail.com>2017-01-31 16:06:33 -0500
committerBen Gamari <ben@smart-cactus.org>2017-01-31 18:50:21 -0500
commit4dfc6d1c40b298d4b8f136e46420227eda60a03d (patch)
treefce2d978323653ff0ff989fdb72f3585be5b4de4 /rts/eventlog
parent44f079f74869d8cb417e2dcc104517ae7f593e5f (diff)
downloadhaskell-4dfc6d1c40b298d4b8f136e46420227eda60a03d.tar.gz
Abstract over the way eventlogs are flushed
Currently eventlog data is always written to a file `progname.eventlog`. This patch introduces the `flushEventLog` field in `RtsConfig` which allows to customize the writing of eventlog data. One possible scenario is the ongoing live-profile-monitor effort by @NCrashed which slurps all eventlog data through `fluchEventLog`. `flushEventLog` takes a buffer with eventlog data and its size and returns `false` (0) in case eventlog data could not be procesed. Reviewers: simonmar, austin, erikd, bgamari Reviewed By: simonmar, bgamari Subscribers: qnikst, thomie, NCrashed Differential Revision: https://phabricator.haskell.org/D2934
Diffstat (limited to 'rts/eventlog')
-rw-r--r--rts/eventlog/EventLog.c128
-rw-r--r--rts/eventlog/EventLog.h3
-rw-r--r--rts/eventlog/EventLogWriter.c122
3 files changed, 175 insertions, 78 deletions
diff --git a/rts/eventlog/EventLog.c b/rts/eventlog/EventLog.c
index 4e4bdb5191..ce4cb3847a 100644
--- a/rts/eventlog/EventLog.c
+++ b/rts/eventlog/EventLog.c
@@ -26,13 +26,7 @@
#include <unistd.h>
#endif
-// PID of the process that writes to event_log_filename (#4512)
-static pid_t event_log_pid = -1;
-
-static char *event_log_filename = NULL;
-
-// File for logging events
-FILE *event_log_file = NULL;
+static const EventLogWriter *event_log_writer;
#define EVENT_LOG_SIZE 2 * (1024 * 1024) // 2MB
@@ -232,55 +226,55 @@ static inline void postInt32(EventsBuf *eb, StgInt32 i)
#define EVENT_SIZE_DYNAMIC (-1)
-void
-initEventLogging(void)
+static void
+initEventLogWriter(void)
{
- StgWord8 t, c;
- uint32_t n_caps;
- char *prog;
-
- prog = stgMallocBytes(strlen(prog_name) + 1, "initEventLogging");
- 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';
- }
+ if (event_log_writer != NULL &&
+ event_log_writer->initEventLogWriter != NULL) {
+ event_log_writer->initEventLogWriter();
}
-#endif
+}
- event_log_filename = stgMallocBytes(strlen(prog)
- + 10 /* .%d */
- + 10 /* .eventlog */,
- "initEventLogging");
+static bool
+writeEventLog(void *eventlog, size_t eventlog_size)
+{
+ if (event_log_writer != NULL &&
+ event_log_writer->writeEventLog != NULL) {
+ return event_log_writer->writeEventLog(eventlog, eventlog_size);
+ } else {
+ return false;
+ }
+}
- if (sizeof(EventDesc) / sizeof(char*) != NUM_GHC_EVENT_TAGS) {
- barf("EventDesc array has the wrong number of elements");
+static void
+stopEventLogWriter(void)
+{
+ if (event_log_writer != NULL &&
+ event_log_writer->stopEventLogWriter != NULL) {
+ event_log_writer->stopEventLogWriter();
}
+}
- 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);
+void
+flushEventLog(void)
+{
+ if (event_log_writer != NULL &&
+ event_log_writer->flushEventLog != NULL) {
+ event_log_writer->flushEventLog();
}
- stgFree(prog);
+}
+
+void
+initEventLogging(const EventLogWriter *ev_writer)
+{
+ StgWord8 t, c;
+ uint32_t n_caps;
+
+ event_log_writer = ev_writer;
+ initEventLogWriter();
- /* Open event log file for writing. */
- if ((event_log_file = fopen(event_log_filename, "wb")) == NULL) {
- sysErrorBelch("initEventLogging: can't open %s", event_log_filename);
- stg_exit(EXIT_FAILURE);
+ if (sizeof(EventDesc) / sizeof(char*) != NUM_GHC_EVENT_TAGS) {
+ barf("EventDesc array has the wrong number of elements");
}
/*
@@ -522,9 +516,7 @@ endEventLogging(void)
// Flush the end of data marker.
printAndClearEventBuf(&eventBuf);
- if (event_log_file != NULL) {
- fclose(event_log_file);
- }
+ stopEventLogWriter();
}
void
@@ -568,26 +560,13 @@ freeEventLogging(void)
if (capEventBuf != NULL) {
stgFree(capEventBuf);
}
- if (event_log_filename != NULL) {
- stgFree(event_log_filename);
- }
-}
-
-void
-flushEventLog(void)
-{
- if (event_log_file != NULL) {
- fflush(event_log_file);
- }
}
void
abortEventLogging(void)
{
freeEventLogging();
- if (event_log_file != NULL) {
- fclose(event_log_file);
- }
+ stopEventLogWriter();
}
/*
@@ -1287,18 +1266,13 @@ void printAndClearEventBuf (EventsBuf *ebuf)
if (ebuf->begin != NULL && ebuf->pos != ebuf->begin)
{
- StgInt8 *begin = ebuf->begin;
- while (begin < ebuf->pos) {
- StgWord64 remain = ebuf->pos - begin;
- StgWord64 written = fwrite(begin, 1, remain, event_log_file);
- if (written == 0) {
- debugBelch(
- "printAndClearEventLog: fwrite() failed to write anything;"
- " tried to write numBytes=%" FMT_Word64, remain);
- resetEventsBuf(ebuf);
- return;
- }
- begin += written;
+ size_t elog_size = ebuf->pos - ebuf->begin;
+ if (!writeEventLog(ebuf->begin, elog_size)) {
+ debugBelch(
+ "printAndClearEventLog: could not flush event log"
+ );
+ resetEventsBuf(ebuf);
+ return;
}
resetEventsBuf(ebuf);
diff --git a/rts/eventlog/EventLog.h b/rts/eventlog/EventLog.h
index 462f5f594e..e36c97353e 100644
--- a/rts/eventlog/EventLog.h
+++ b/rts/eventlog/EventLog.h
@@ -10,6 +10,7 @@
#define EVENTLOG_H
#include "rts/EventLogFormat.h"
+#include "rts/EventLogWriter.h"
#include "Capability.h"
#include "BeginPrivate.h"
@@ -21,7 +22,7 @@
*/
extern char *EventTagDesc[];
-void initEventLogging(void);
+void initEventLogging(const EventLogWriter *writer);
void endEventLogging(void);
void freeEventLogging(void);
void abortEventLogging(void); // #4512 - after fork child needs to abort
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
+};