[gjs/wip/tko/116-mem-track: 1/4] context: dump heaps on signal
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/tko/116-mem-track: 1/4] context: dump heaps on signal
- Date: Sun, 4 Feb 2018 05:59:04 +0000 (UTC)
commit 4eb25d23deaac3f324931c9dffff308c0f060bef
Author: Tommi Komulainen <tko litl com>
Date: Mon Jan 26 14:05:23 2009 +0000
context: dump heaps on signal
When GJS_DEBUG_HEAP_OUTPUT environment variable is set, set up SIGUSR1
signal handler to dump JS heaps (using JS_DumpHeap) to file to aid
debugging memory leaks.
The log files generated will be ${GJS_DEBUG_HEAP_OUTPUT}.${pid}.${counter}
Usage:
$ GJS_DEBUG_HEAP_OUTPUT=/tmp/gjs-heap gjs-console ...
$ kill -USR1 `pidof gjs-console`
$ less /tmp/gjs-heap.`pidof gjs-console`.0
(Philip Chimento: rebased and updated coding style)
gjs/context.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 79 insertions(+)
---
diff --git a/gjs/context.cpp b/gjs/context.cpp
index aa9b2a09..d281dd91 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -24,6 +24,9 @@
#include <config.h>
#include <array>
+#include <signal.h>
+#include <sys/types.h>
+#include <unistd.h>
#include <unordered_map>
#include <gio/gio.h>
@@ -34,6 +37,7 @@
#include "importer.h"
#include "jsapi-util.h"
#include "jsapi-wrapper.h"
+#include "mem.h"
#include "native.h"
#include "profiler-private.h"
#include "byteArray.h"
@@ -129,6 +133,79 @@ enum {
static GMutex contexts_lock;
static GList *all_contexts = NULL;
+static char *dump_heap_output = nullptr;
+static unsigned dump_heap_idle_id = 0;
+
+static void
+gjs_context_dump_heap(GjsContext *js_context,
+ FILE *fp)
+{
+ js::DumpHeap(js_context->context, fp, js::IgnoreNurseryObjects);
+}
+
+static void
+gjs_context_dump_heaps(void)
+{
+ static unsigned counter = 0;
+
+ gjs_memory_report("signal handler", false);
+
+ /* dump to sequential files to allow easier comparisons */
+ GjsAutoChar filename = g_strdup_printf("%s.%jd.%u", dump_heap_output,
+ intmax_t(getpid()), counter);
+ ++counter;
+
+ FILE *fp = fopen(filename, "w");
+ if (!fp)
+ return;
+
+ for (GList *l = all_contexts; l; l = g_list_next(l)) {
+ auto js_context = static_cast<GjsContext *>(l->data);
+ gjs_context_dump_heap(js_context, fp);
+ }
+
+ fclose(fp);
+}
+
+static gboolean
+dump_heap_idle(gpointer user_data)
+{
+ dump_heap_idle_id = 0;
+
+ gjs_context_dump_heaps();
+
+ return false;
+}
+
+static void
+dump_heap_signal_handler(int signum)
+{
+ if (dump_heap_idle_id == 0)
+ dump_heap_idle_id = g_idle_add_full(G_PRIORITY_HIGH_IDLE,
+ dump_heap_idle, nullptr, nullptr);
+}
+
+static void
+setup_dump_heap(void)
+{
+ static bool dump_heap_initialized = false;
+ if (!dump_heap_initialized) {
+ dump_heap_initialized = true;
+
+ /* install signal handler only if environment variable is set */
+ const char *heap_output = g_getenv("GJS_DEBUG_HEAP_OUTPUT");
+ if (heap_output) {
+ struct sigaction sa;
+
+ dump_heap_output = g_strdup(heap_output);
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = dump_heap_signal_handler;
+ sigaction(SIGUSR1, &sa, nullptr);
+ }
+ }
+}
+
static void
gjs_context_init(GjsContext *js_context)
{
@@ -410,6 +487,8 @@ gjs_context_constructed(GObject *object)
g_mutex_lock (&contexts_lock);
all_contexts = g_list_prepend(all_contexts, object);
g_mutex_unlock (&contexts_lock);
+
+ setup_dump_heap();
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]