Skip to content

Commit cc50c36

Browse files
author
John French
committed
tsfn: fix crash on releasing tsfn
Refs: nodejs/node-addon-api#531 PR-URL: nodejs/node-addon-api#532 Reviewed-By: Gabriel Schulhof <[email protected]> Reviewed-By: Michael Dawson <[email protected]>
1 parent b9c1e8d commit cc50c36

File tree

7 files changed

+49
-3
lines changed

7 files changed

+49
-3
lines changed

napi-inl.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3926,12 +3926,12 @@ inline ThreadSafeFunction ThreadSafeFunction::New(napi_env env,
39263926
}
39273927

39283928
inline ThreadSafeFunction::ThreadSafeFunction()
3929-
: _tsfn(new napi_threadsafe_function(nullptr)) {
3929+
: _tsfn(new napi_threadsafe_function(nullptr), _d) {
39303930
}
39313931

39323932
inline ThreadSafeFunction::ThreadSafeFunction(
39333933
napi_threadsafe_function tsfn)
3934-
: _tsfn(new napi_threadsafe_function(tsfn)) {
3934+
: _tsfn(new napi_threadsafe_function(tsfn), _d) {
39353935
}
39363936

39373937
inline ThreadSafeFunction::ThreadSafeFunction(ThreadSafeFunction&& other)

napi.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2029,8 +2029,13 @@ namespace Napi {
20292029
napi_value jsCallback,
20302030
void* context,
20312031
void* data);
2032+
struct Deleter {
2033+
// napi_threadsafe_function is managed by Node.js, leave it alone.
2034+
void operator()(napi_threadsafe_function*) const {};
2035+
};
20322036

2033-
std::unique_ptr<napi_threadsafe_function> _tsfn;
2037+
std::unique_ptr<napi_threadsafe_function, Deleter> _tsfn;
2038+
Deleter _d;
20342039
};
20352040
#endif
20362041

test/binding.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ Object InitObjectDeprecated(Env env);
3434
#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
3535
Object InitPromise(Env env);
3636
#if (NAPI_VERSION > 3)
37+
Object InitThreadSafeFunctionPtr(Env env);
3738
Object InitThreadSafeFunction(Env env);
3839
#endif
3940
Object InitTypedArray(Env env);
@@ -75,6 +76,7 @@ Object Init(Env env, Object exports) {
7576
#endif // !NODE_ADDON_API_DISABLE_DEPRECATED
7677
exports.Set("promise", InitPromise(env));
7778
#if (NAPI_VERSION > 3)
79+
exports.Set("threadsafe_function_ptr", InitThreadSafeFunctionPtr(env));
7880
exports.Set("threadsafe_function", InitThreadSafeFunction(env));
7981
#endif
8082
exports.Set("typedarray", InitTypedArray(env));

test/binding.gyp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
'object/object.cc',
3333
'object/set_property.cc',
3434
'promise.cc',
35+
'threadsafe_function/threadsafe_function_ptr.cc',
3536
'threadsafe_function/threadsafe_function.cc',
3637
'typedarray.cc',
3738
'objectwrap.cc',

test/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ let testModules = [
3636
'object/object_deprecated',
3737
'object/set_property',
3838
'promise',
39+
'threadsafe_function/threadsafe_function_ptr',
3940
'threadsafe_function/threadsafe_function',
4041
'typedarray',
4142
'typedarray-bigint',
@@ -64,6 +65,7 @@ if ((process.env.npm_config_NAPI_VERSION !== undefined) &&
6465

6566
if ((process.env.npm_config_NAPI_VERSION !== undefined) &&
6667
(process.env.npm_config_NAPI_VERSION < 4)) {
68+
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function_ptr'), 1);
6769
testModules.splice(testModules.indexOf('threadsafe_function/threadsafe_function'), 1);
6870
}
6971

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include "napi.h"
2+
3+
#if (NAPI_VERSION > 3)
4+
5+
using namespace Napi;
6+
7+
namespace {
8+
9+
static Value Test(const CallbackInfo& info) {
10+
Object resource = info[0].As<Object>();
11+
Function cb = info[1].As<Function>();
12+
ThreadSafeFunction tsfn = ThreadSafeFunction::New(info.Env(), cb, resource, "Test", 1, 1);
13+
tsfn.Release();
14+
return info.Env().Undefined();
15+
}
16+
17+
}
18+
19+
Object InitThreadSafeFunctionPtr(Env env) {
20+
Object exports = Object::New(env);
21+
exports["test"] = Function::New(env, Test);
22+
23+
return exports;
24+
}
25+
26+
#endif
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
'use strict';
2+
3+
const buildType = process.config.target_defaults.default_configuration;
4+
5+
test(require(`../build/${buildType}/binding.node`));
6+
test(require(`../build/${buildType}/binding_noexcept.node`));
7+
8+
function test(binding) {
9+
binding.threadsafe_function_ptr.test({}, () => {});
10+
}

0 commit comments

Comments
 (0)