diff options
| author | LemonBoy <thatlemon@gmail.com> | 2021-05-20 15:26:17 +0200 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2021-05-20 15:26:17 +0200 |
| commit | abfe7f96dd45e22d43c3e14ed64e1fbb8e94b419 (patch) | |
| tree | e4283d3203940eb4588d8c87f12964ad6902dfb7 /lib/std | |
| parent | 992c02ab95e8297a1558bcf011f15a5cf1cd8e1b (diff) | |
| download | zig-abfe7f96dd45e22d43c3e14ed64e1fbb8e94b419.tar.gz zig-abfe7f96dd45e22d43c3e14ed64e1fbb8e94b419.zip | |
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.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/crypto/tlcsprng.zig | 20 |
1 files changed, 12 insertions, 8 deletions
diff --git a/lib/std/crypto/tlcsprng.zig b/lib/std/crypto/tlcsprng.zig index 1e39b125f6..c23e99e2dd 100644 --- a/lib/std/crypto/tlcsprng.zig +++ b/lib/std/crypto/tlcsprng.zig @@ -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 { |
