Skip to content

Commit

Permalink
gumjs: Relinquish JS lock while unreffing modules
Browse files Browse the repository at this point in the history
To avoid deadlocking in case dispose() releases a cached handle. Such an
operation typically requires acquiring a runtime linker lock. Another
thread might already be holding that lock while waiting for the JS lock.
A common scenario for that to happen is that the agent registers a
callback with the runtime linker, called whenever a module is loaded or
unloaded.

Kudos to @mrmacete for reporting.
  • Loading branch information
oleavr committed Jan 9, 2025
1 parent 0fb88ca commit 5cb16b8
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
10 changes: 10 additions & 0 deletions bindings/gumjs/gumquickmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,17 @@ GUMJS_DEFINE_CONSTRUCTOR (gumjs_module_construct)
GUMJS_DEFINE_FINALIZER (gumjs_module_finalize)
{
GumModule * m;
GumQuickScope scope = GUM_QUICK_SCOPE_INIT (core);

m = JS_GetOpaque (val, gumjs_get_parent_module (core)->module_class);
if (m == NULL)
return;

_gum_quick_scope_suspend (&scope);

g_object_unref (m);

_gum_quick_scope_resume (&scope);
}

GUMJS_DEFINE_GETTER (gumjs_module_get_name)
Expand Down Expand Up @@ -782,12 +787,17 @@ GUMJS_DEFINE_CONSTRUCTOR (gumjs_module_map_construct)
GUMJS_DEFINE_FINALIZER (gumjs_module_map_finalize)
{
GumModuleMap * m;
GumQuickScope scope = GUM_QUICK_SCOPE_INIT (core);

m = JS_GetOpaque (val, gumjs_get_parent_module (core)->module_map_class);
if (m == NULL)
return;

_gum_quick_scope_suspend (&scope);

g_object_unref (m);

_gum_quick_scope_resume (&scope);
}

GUMJS_DEFINE_GETTER (gumjs_module_map_get_handle)
Expand Down
12 changes: 10 additions & 2 deletions bindings/gumjs/gumv8module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,11 @@ _gum_v8_module_new_take_handle (GumModule * handle,
static void
gum_v8_module_value_free (GumV8ModuleValue * value)
{
g_object_unref (value->handle);
{
ScriptUnlocker unlocker (value->module->core);

g_object_unref (value->handle);
}

delete value->wrapper;

Expand Down Expand Up @@ -884,7 +888,11 @@ gum_v8_module_map_new (Local<Object> wrapper,
static void
gum_v8_module_map_free (GumV8ModuleMap * map)
{
g_object_unref (map->handle);
{
ScriptUnlocker unlocker (map->module->core);

g_object_unref (map->handle);
}

delete map->wrapper;

Expand Down

0 comments on commit 5cb16b8

Please sign in to comment.