Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions bindings/napi/root.zig
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,14 @@ comptime {
/// and torn down only when the last environment exits.
var env_refcount: std.atomic.Value(u32) = std.atomic.Value(u32).init(0);

/// Guards shared state initialization so that concurrent `register` calls
/// (e.g. from Node.js Worker threads) cannot observe partially-initialized state.
var init_mutex: std.Thread.Mutex = .{};

const EnvCleanup = struct {
fn hook(_: *EnvCleanup) void {
init_mutex.lock();
defer init_mutex.unlock();
if (env_refcount.fetchSub(1, .acq_rel) == 1) {
// Last environment — tear down shared state.
config.state.deinit();
Expand All @@ -33,11 +39,20 @@ const EnvCleanup = struct {
var env_cleanup: EnvCleanup = .{};

fn register(env: napi.Env, exports: napi.Value) !void {
if (env_refcount.fetchAdd(1, .monotonic) == 0) {
// First environment — initialize shared state.
try pool.state.init();
try pubkeys.state.init();
config.state.init();
{
init_mutex.lock();
defer init_mutex.unlock();
if (env_refcount.fetchAdd(1, .monotonic) == 0) {
Comment thread
GrapeBaBa marked this conversation as resolved.
// First environment — initialize shared state.
// On failure, roll back the refcount so the next caller retries.
Comment thread
GrapeBaBa marked this conversation as resolved.
errdefer {
const old = env_refcount.fetchSub(1, .monotonic);
std.debug.assert(old == 1);
}
try pool.state.init();
try pubkeys.state.init();
config.state.init();
}
}

try env.addEnvCleanupHook(EnvCleanup, &env_cleanup, EnvCleanup.hook);
Expand Down
4 changes: 2 additions & 2 deletions src/bls/ThreadPool.zig
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ fn execVerifyMulti(pool: *ThreadPool, job: *VerifyMultiJob, worker_index: usize)
while (true) {
const i = job.counter.fetchAdd(1, .monotonic);
if (i >= n_elems) break;
if (job.err_flag.load(.acquire)) break;
if (job.err_flag.load(.monotonic)) break;

did_work = true;

Expand Down Expand Up @@ -257,7 +257,7 @@ fn execAggVerify(pool: *ThreadPool, job: *AggVerifyJob, worker_index: usize) voi
while (true) {
const i = job.counter.fetchAdd(1, .monotonic);
if (i >= job.n_elems) break;
if (job.err_flag.load(.acquire)) break;
if (job.err_flag.load(.monotonic)) break;

did_work = true;

Expand Down
Loading