std: Call pthread_atfork only once

Some libc implementations (glib) deduplicate identical hooks, others
(musl, macos) do not and blindly append them to an internal list.
Ensure there's only a single call to pthread_atfork to prevent unbounded
memory use when lots of threads/forks are used.
This commit is contained in:
LemonBoy 2021-05-20 15:26:17 +02:00
parent 992c02ab95
commit abfe7f96dd

View File

@ -48,6 +48,16 @@ const Context = struct {
gimli: std.crypto.core.Gimli,
};
var install_atfork_handler = std.once(struct {
// Install the global handler only once.
// The same handler is shared among threads and is inherinted by fork()-ed
// processes.
fn do() void {
const r = std.c.pthread_atfork(null, null, childAtForkHandler);
std.debug.assert(r == 0);
}
}.do);
threadlocal var wipe_mem: []align(mem.page_size) u8 = &[_]u8{};
fn tlsCsprngFill(_: *const std.rand.Random, buffer: []u8) void {
@ -135,14 +145,8 @@ fn tlsCsprngFill(_: *const std.rand.Random, buffer: []u8) void {
}
fn setupPthreadAtforkAndFill(buffer: []u8) void {
const failed = std.c.pthread_atfork(null, null, childAtForkHandler) != 0;
if (failed) {
const ctx = @ptrCast(*Context, wipe_mem.ptr);
ctx.init_state = .failed;
return fillWithOsEntropy(buffer);
} else {
return initAndFill(buffer);
}
install_atfork_handler.call();
return initAndFill(buffer);
}
fn childAtForkHandler() callconv(.C) void {