| ... | ... | @@ -48,6 +48,16 @@ const Context = struct { |
| 48 | 48 | gimli: std.crypto.core.Gimli, |
| 49 | 49 | }; |
| 50 | 50 | |
| 51 | var install_atfork_handler = std.once(struct { |
| 52 | // Install the global handler only once. |
| 53 | // The same handler is shared among threads and is inherinted by fork()-ed |
| 54 | // processes. |
| 55 | fn do() void { |
| 56 | const r = std.c.pthread_atfork(null, null, childAtForkHandler); |
| 57 | std.debug.assert(r == 0); |
| 58 | } |
| 59 | }.do); |
| 60 | |
| 51 | 61 | threadlocal var wipe_mem: []align(mem.page_size) u8 = &[_]u8{}; |
| 52 | 62 | |
| 53 | 63 | fn tlsCsprngFill(_: *const std.rand.Random, buffer: []u8) void { |
| ... | ... | @@ -135,14 +145,8 @@ fn tlsCsprngFill(_: *const std.rand.Random, buffer: []u8) void { |
| 135 | 145 | } |
| 136 | 146 | |
| 137 | 147 | fn setupPthreadAtforkAndFill(buffer: []u8) void { |
| 138 | | const failed = std.c.pthread_atfork(null, null, childAtForkHandler) != 0; |
| 139 | | if (failed) { |
| 140 | | const ctx = @ptrCast(*Context, wipe_mem.ptr); |
| 141 | | ctx.init_state = .failed; |
| 142 | | return fillWithOsEntropy(buffer); |
| 143 | | } else { |
| 144 | | return initAndFill(buffer); |
| 145 | | } |
| 148 | install_atfork_handler.call(); |
| 149 | return initAndFill(buffer); |
| 146 | 150 | } |
| 147 | 151 | |
| 148 | 152 | fn childAtForkHandler() callconv(.C) void { |