From 31e7bf5270e5d05ee8510810db10da1cea3194e3 Mon Sep 17 00:00:00 2001 From: Mahdi Sharifi Date: Wed, 15 May 2024 14:22:02 +0330 Subject: [PATCH] Reproduce Metacall's strange behavior bug with bulk calls --- .../node_loader/source/node_loader_impl.cpp | 5 +- ...etacall_node_multithread_deadlock_test.cpp | 50 ++++++++++++------- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/source/loaders/node_loader/source/node_loader_impl.cpp b/source/loaders/node_loader/source/node_loader_impl.cpp index cba02cd78..8f9f0beb4 100644 --- a/source/loaders/node_loader/source/node_loader_impl.cpp +++ b/source/loaders/node_loader/source/node_loader_impl.cpp @@ -1379,6 +1379,8 @@ function_return function_node_interface_invoke(function func, function_impl impl node_impl->func_call_safe->recv = NULL; node_impl->func_call_safe->ret = NULL; +RETRY_LOCK: + /* Check if we are in the JavaScript thread */ if (node_impl->js_thread_id == std::this_thread::get_id()) { @@ -1430,7 +1432,8 @@ function_return function_node_interface_invoke(function func, function_impl impl } else { - log_write("metacall", LOG_LEVEL_ERROR, "Potential deadlock detected in function_node_interface_invoke, the call has not been executed in order to avoid the deadlock"); + // log_write("metacall", LOG_LEVEL_ERROR, "Potential deadlock detected in function_node_interface_invoke, the call has not been executed in order to avoid the deadlock"); + goto RETRY_LOCK; } return ret; diff --git a/source/tests/metacall_node_multithread_deadlock_test/source/metacall_node_multithread_deadlock_test.cpp b/source/tests/metacall_node_multithread_deadlock_test/source/metacall_node_multithread_deadlock_test.cpp index b6688e963..5233af57a 100644 --- a/source/tests/metacall_node_multithread_deadlock_test/source/metacall_node_multithread_deadlock_test.cpp +++ b/source/tests/metacall_node_multithread_deadlock_test/source/metacall_node_multithread_deadlock_test.cpp @@ -42,41 +42,53 @@ TEST_F(metacall_node_multithread_deadlock_test, DefaultConstructor) /* NodeJS */ #if defined(OPTION_BUILD_LOADERS_NODE) { + // static const char buffer[] = + // "async function f() { return new Promise(resolve => setTimeout(() => resolve(65), 1000)) }\n" + // "module.exports = { f };\n"; + static const char buffer[] = + "function f() { return 65; }\n" + "module.exports = { f };\n"; + + ASSERT_EQ((int)0, (int)metacall_load_from_memory("node", buffer, sizeof(buffer), NULL)); + /* Test if the loader can cause a data race */ auto runner = []() { /* Running it over and over again making sure data race is attempted */ - for (size_t i = 0; i < 2000000; i++) + for (size_t i = 0; i < 200; i++) { - void *future = metacall("j"); + void *future = metacall("f"); EXPECT_NE((void *)NULL, (void *)future); + // EXPECT_EQ((enum metacall_value_id)metacall_value_id(future), (enum metacall_value_id)METACALL_FUTURE); + EXPECT_EQ((enum metacall_value_id)metacall_value_id(future), (enum metacall_value_id)METACALL_DOUBLE); + + EXPECT_EQ((double)65.0, (double)metacall_value_to_double(future)); - EXPECT_EQ((enum metacall_value_id)metacall_value_id(future), (enum metacall_value_id)METACALL_FUTURE); - void *ret = metacall_await_future( - metacall_value_to_future(future), - [](void *result, void *) -> void * { - EXPECT_NE((void *)NULL, (void *)result); + // void *ret = metacall_await_future( + // metacall_value_to_future(future), + // [](void *result, void *) -> void * { + // EXPECT_NE((void *)NULL, (void *)result); - EXPECT_EQ((enum metacall_value_id)metacall_value_id(result), (enum metacall_value_id)METACALL_DOUBLE); + // EXPECT_EQ((enum metacall_value_id)metacall_value_id(result), (enum metacall_value_id)METACALL_DOUBLE); - EXPECT_EQ((double)34.0, (double)metacall_value_to_double(result)); + // EXPECT_EQ((double)65.0, (double)metacall_value_to_double(result)); - // ++success_callbacks; + // // ++success_callbacks; - return metacall_value_create_double(155.0); - }, - [](void *, void *) -> void * { - int this_should_never_be_executed = 0; + // return metacall_value_create_double(155.0); + // }, + // [](void *, void *) -> void * { + // int this_should_never_be_executed = 0; - EXPECT_EQ((int)1, (int)this_should_never_be_executed); + // EXPECT_EQ((int)1, (int)this_should_never_be_executed); - return NULL; - }, - NULL); + // return NULL; + // }, + // NULL); metacall_value_destroy(future); - metacall_value_destroy(ret); + // metacall_value_destroy(ret); } };