diff --git a/src/main.zig b/src/main.zig index bbad2a6..21ff791 100644 --- a/src/main.zig +++ b/src/main.zig @@ -19,6 +19,7 @@ const SpeechHandler = struct { recoverable_error_count: u32 = 0, exec_program: ?[]const u8 = null, child_processes: std.ArrayList(*Process) = .{}, + child_processes_mutex: std.Thread.Mutex = .{}, reclaiming: std.atomic.Value(bool) = std.atomic.Value(bool).init(false), const max_children = 5; @@ -52,6 +53,10 @@ const SpeechHandler = struct { } fn exec(self: *SpeechHandler, text: []const u8) !void { const program = self.exec_program.?; // should only be called when exec_program is not null + + self.child_processes_mutex.lock(); + defer self.child_processes_mutex.unlock(); + // We need to be able to clean up at some point in the future, but we don't // care about these processes otherwise const process = try self.allocator.create(Process); @@ -76,6 +81,10 @@ const SpeechHandler = struct { // This code should present that if (self.reclaiming.cmpxchgStrong(false, true, .acquire, .acquire)) |_| return; defer self.reclaiming.store(false, .release); + + self.child_processes_mutex.lock(); + defer self.child_processes_mutex.unlock(); + if (!reap_all and self.child_processes.items.len <= max_children) return; std.log.debug("Reclaiming memory from {s} processes", .{if (reap_all) "ALL" else "completed"}); if (self.child_processes.items.len == 0) return; @@ -266,6 +275,10 @@ fn signalAction(sig: i32, info: *const std.posix.siginfo_t, _: ?*anyopaque) call if (sig == std.posix.SIG.CHLD) { const pid = info.fields.common.first.piduid.pid; std.log.debug("SIGCHLD on pid {d}", .{pid}); + + handler.child_processes_mutex.lock(); + defer handler.child_processes_mutex.unlock(); + for (handler.child_processes.items) |proc| { if (proc.child) |child| { if (child.id == pid) {