Fix OOM handling to be thread-safe

This commit is contained in:
Yorhel 2024-07-17 11:48:06 +02:00
parent 6bb31a4653
commit e5508ba9b4
2 changed files with 20 additions and 8 deletions

View file

@ -429,6 +429,8 @@ fn readExcludeFile(path: [:0]const u8) !void {
} }
pub fn main() void { pub fn main() void {
ui.main_thread = std.Thread.getCurrentId();
// Grab thousands_sep from the current C locale. // Grab thousands_sep from the current C locale.
_ = c.setlocale(c.LC_ALL, ""); _ = c.setlocale(c.LC_ALL, "");
if (c.localeconv()) |locale| { if (c.localeconv()) |locale| {
@ -574,6 +576,8 @@ var event_delay_timer: std.time.Timer = undefined;
// Draw the screen and handle the next input event. // Draw the screen and handle the next input event.
// In non-blocking mode, screen drawing is rate-limited to keep this function fast. // In non-blocking mode, screen drawing is rate-limited to keep this function fast.
pub fn handleEvent(block: bool, force_draw: bool) void { pub fn handleEvent(block: bool, force_draw: bool) void {
while (ui.oom_threads.load(.monotonic) > 0) ui.oom();
if (block or force_draw or event_delay_timer.read() > config.update_delay) { if (block or force_draw or event_delay_timer.read() > config.update_delay) {
if (ui.inited) _ = ui.c.erase(); if (ui.inited) _ = ui.c.erase();
switch (state) { switch (state) {

View file

@ -18,6 +18,8 @@ pub const c = @cImport({
}); });
pub var inited: bool = false; pub var inited: bool = false;
pub var main_thread: std.Thread.Id = undefined;
pub var oom_threads = std.atomic.Value(usize).init(0);
pub var rows: u32 = undefined; pub var rows: u32 = undefined;
pub var cols: u32 = undefined; pub var cols: u32 = undefined;
@ -43,8 +45,9 @@ pub fn quit() noreturn {
// Also, init() and other ncurses-related functions may have hidden allocation, // Also, init() and other ncurses-related functions may have hidden allocation,
// no clue if ncurses will consistently report OOM, but we're not handling that // no clue if ncurses will consistently report OOM, but we're not handling that
// right now. // right now.
// TODO: Make thread-safe!
pub fn oom() void { pub fn oom() void {
@setCold(true);
if (main_thread == std.Thread.getCurrentId()) {
const haveui = inited; const haveui = inited;
deinit(); deinit();
const stderr = std.io.getStdErr(); const stderr = std.io.getStdErr();
@ -52,6 +55,11 @@ pub fn oom() void {
std.time.sleep(std.time.ns_per_s); std.time.sleep(std.time.ns_per_s);
if (haveui) if (haveui)
init(); init();
} else {
_ = oom_threads.fetchAdd(1, .monotonic);
std.time.sleep(std.time.ns_per_s);
_ = oom_threads.fetchSub(1, .monotonic);
}
} }
// Dumb strerror() alternative for Zig file I/O, not complete. // Dumb strerror() alternative for Zig file I/O, not complete.