summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiovanni Campagna <gcampagna@src.gnome.org>2012-07-04 22:32:03 +0200
committerGiovanni Campagna <gcampagna@src.gnome.org>2012-10-30 17:23:36 +0100
commit83a6e435711091b98990c311cd8c1d55bcc834cb (patch)
tree7711f2b3ff04e921daf411f08116675e4280176a
parentd10cdb471bd101065961bb2b6321630ca15ef356 (diff)
downloadgjs-83a6e435711091b98990c311cd8c1d55bcc834cb.tar.gz
Keep Alive: add a debugging method to print all active roots
Adds a print_roots() to keep-alive objects (such as __gc_this_on_context_destroy, where GObjects are stored), which prints a dump of all objects known to it on stderr. This is primarily meant to debug GObject cycles and leaks that are not detected. https://bugzilla.gnome.org/show_bug.cgi?id=679688
-rw-r--r--gi/keep-alive.c71
1 files changed, 70 insertions, 1 deletions
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index d45740a3..afacf14a 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -165,6 +165,74 @@ keep_alive_trace(JSTracer *tracer,
priv->inside_trace = FALSE;
}
+static char*
+jsobj_to_string(JSContext* cx, JSObject *obj)
+{
+ char* value = NULL;
+
+ if (JS_ObjectIsFunction(cx, obj)) {
+ JSFunction *fn = JS_ValueToFunction(cx, OBJECT_TO_JSVAL(obj));
+ JSString *str;
+
+ str = JS_GetFunctionId(fn);
+ if (str) {
+ value = NULL;
+ gjs_try_string_to_utf8(cx, STRING_TO_JSVAL(str), &value, NULL);
+ } else {
+ value = g_strdup ("anonymous function");
+ }
+ } else {
+ value = g_strdup_printf("[object %s]", JS_GetClass(cx, obj)->name);
+ }
+
+ if (!value)
+ value = g_strdup ("[unknown object]");
+ return value;
+}
+
+static void
+print_foreach(void *key,
+ void *value,
+ void *data)
+{
+ Child *child = value;
+ JSContext *context = data;
+
+ if (child->child != NULL) {
+ char *string;
+
+ string = jsobj_to_string(context, child->child);
+ g_printerr("%p: %s\n", child->child, string);
+
+ g_free(string);
+ }
+}
+
+static JSBool
+print_roots (JSContext *context,
+ uintN argc,
+ jsval *vp)
+{
+ JSObject *obj = JS_THIS_OBJECT(context, vp);
+ KeepAlive *priv;
+
+ JS_BeginRequest(context);
+
+ priv = priv_from_js(context, obj);
+
+ if (priv == NULL) /* prototype */
+ return JS_TRUE;
+
+ g_printerr("**** BEGIN GJS root table dump ****\n");
+ g_hash_table_foreach(priv->children, print_foreach, context);
+ g_printerr("**** END GJS root table dump ****\n");
+
+ JS_SET_RVAL(context, vp, JSVAL_VOID);
+ JS_EndRequest(context);
+
+ return JS_TRUE;
+}
+
/* The bizarre thing about this vtable is that it applies to both
* instances of the object, and to the prototype that instances of the
* class have.
@@ -201,7 +269,8 @@ static JSPropertySpec gjs_keep_alive_proto_props[] = {
};
static JSFunctionSpec gjs_keep_alive_proto_funcs[] = {
- { NULL }
+ { "print_roots", (JSNative)print_roots, 0, 0 },
+ { NULL },
};
JSObject*