Skip to content

Commit 3481e82

Browse files
author
Mariusz Pasinski
committed
fix: defer calling napi_module_register() until weak node api injection
Early implementation just to get the app running. Without this change, the application crashes immediately after process was created. This is triggered by dynamic linker load addons at start up, and the "twisted addon" has a function decorated with `__attribute__ ((constructor))` which calls `napi_module_register()` before even Weak NodeAPI has change to inject the proper function pointers...
1 parent 8cd8791 commit 3481e82

File tree

2 files changed

+43
-4
lines changed

2 files changed

+43
-4
lines changed

packages/host/scripts/generate-weak-node-api-injector.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export function generateSource(functions: FunctionDecl[]) {
4242
4343
log_debug("Injecting WeakNodeApiHost");
4444
inject_weak_node_api_host(WeakNodeApiHost {
45+
.napi_module_register = napi_module_register,
4546
${functions
4647
.filter(({ kind }) => kind === "engine")
4748
.flatMap(({ name }) => `.${name} = ${name},`)

packages/host/scripts/generate-weak-node-api.ts

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,43 @@ export function generateHeader(functions: FunctionDecl[]) {
3333
* Generates source code for a version script for the given Node API version.
3434
*/
3535
export function generateSource(functions: FunctionDecl[]) {
36+
const interceptModuleRegisterCalls = true;
3637
return [
3738
"// This file is generated by react-native-node-api",
39+
`#define WITH_DEFERRED_NAPI_MODULE_REGISTER ${interceptModuleRegisterCalls ? 1 : 0}`,
3840
`#include "weak_node_api.hpp"`, // Generated header
41+
"",
42+
// Declare globals needed for bookkeeping intercepted calls
43+
"#if WITH_DEFERRED_NAPI_MODULE_REGISTER",
44+
"#include <mutex>",
45+
"#include <vector>",
46+
"std::mutex g_internal_state_mutex;",
47+
"std::vector<napi_module*> g_pending_modules;",
48+
"#endif // WITH_DEFERRED_NAPI_MODULE_REGISTER",
49+
"",
3950
// Generate the struct of function pointers
4051
"WeakNodeApiHost g_host;",
4152
"void inject_weak_node_api_host(const WeakNodeApiHost& host) {",
4253
" g_host = host;",
54+
"",
55+
"#if WITH_DEFERRED_NAPI_MODULE_REGISTER",
56+
" // Flush pending `napi_module_register()` calls",
57+
" if (nullptr != host.napi_module_register) {",
58+
" std::lock_guard<std::mutex> lock(g_internal_state_mutex);",
59+
" fprintf(stderr,",
60+
` "Flushing %zu intercepted calls to 'napi_module_register'...\\n",`,
61+
" g_pending_modules.size());",
62+
" for (napi_module *module : g_pending_modules) {",
63+
" host.napi_module_register(module);",
64+
" }",
65+
" g_pending_modules.clear();",
66+
" }",
67+
"#endif // WITH_DEFERRED_NAPI_MODULE_REGISTER",
4368
"};",
44-
``,
69+
"",
4570
// Generate function calling into the host
4671
...functions.flatMap(({ returnType, noReturn, name, argumentTypes }) => {
72+
const isDeferrable = name === "napi_module_register";
4773
return [
4874
`extern "C" ${returnType} ${
4975
noReturn ? " __attribute__((noreturn))" : ""
@@ -52,14 +78,26 @@ export function generateSource(functions: FunctionDecl[]) {
5278
.join(", ")}) {`,
5379
`if (g_host.${name} == nullptr) {`,
5480
` fprintf(stderr, "Node-API function '${name}' called before it was injected!\\n");`,
55-
" abort();",
56-
"}",
57-
(returnType === "void" ? "" : "return ") +
81+
...(isDeferrable ? [
82+
"#if WITH_DEFERRED_NAPI_MODULE_REGISTER",
83+
" {",
84+
" std::lock_guard<std::mutex> guard(g_internal_state_mutex);",
85+
" g_pending_modules.push_back(arg0);",
86+
" }",
87+
"#else",
88+
" abort();",
89+
"#endif // WITH_DEFERRED_NAPI_MODULE_REGISTER",
90+
] : [
91+
" abort();",
92+
]),
93+
"} else {",
94+
" " + (returnType === "void" ? "" : "return ") +
5895
"g_host." +
5996
name +
6097
"(" +
6198
argumentTypes.map((_, index) => `arg${index}`).join(", ") +
6299
");",
100+
"}",
63101
"};",
64102
];
65103
}),

0 commit comments

Comments
 (0)