termio/exec: make sure that process is dead before killing read thread

This commit is contained in:
Mitchell Hashimoto
2023-08-07 21:13:33 -07:00
parent b5bb3b3739
commit e2e876bfa1

View File

@ -217,15 +217,16 @@ pub fn threadExit(self: *Exec, data: ThreadData) void {
// Clear out our data since we're not active anymore. // Clear out our data since we're not active anymore.
self.data = null; self.data = null;
// Quit our read thread first so that we aren't simultaneously
// performing a read/close on the pty fd.
_ = std.os.write(data.read_thread_pipe, "x") catch |err|
log.warn("error writing to read thread quit pipe err={}", .{err});
data.read_thread.join();
// Stop our subprocess // Stop our subprocess
if (data.ev.process_exited) self.subprocess.externalExit(); if (data.ev.process_exited) self.subprocess.externalExit();
self.subprocess.stop(); self.subprocess.stop();
// Quit our read thread after exiting the subprocess so that
// we don't get stuck waiting for data to stop flowing if it is
// a particularly noisy process.
_ = std.os.write(data.read_thread_pipe, "x") catch |err|
log.warn("error writing to read thread quit pipe err={}", .{err});
data.read_thread.join();
} }
/// Update the configuration. /// Update the configuration.
@ -671,6 +672,7 @@ const Subprocess = struct {
/// Clean up the subprocess. This will stop the subprocess if it is started. /// Clean up the subprocess. This will stop the subprocess if it is started.
pub fn deinit(self: *Subprocess) void { pub fn deinit(self: *Subprocess) void {
self.stop(); self.stop();
if (self.pty) |*pty| pty.deinit();
self.arena.deinit(); self.arena.deinit();
self.* = undefined; self.* = undefined;
} }
@ -779,7 +781,8 @@ const Subprocess = struct {
} }
/// Stop the subprocess. This is safe to call anytime. This will wait /// Stop the subprocess. This is safe to call anytime. This will wait
/// for the subprocess to end so it will block. /// for the subprocess to end so it will block. This does not close
/// the pty.
pub fn stop(self: *Subprocess) void { pub fn stop(self: *Subprocess) void {
// Kill our command // Kill our command
if (self.command) |*cmd| { if (self.command) |*cmd| {
@ -800,14 +803,6 @@ const Subprocess = struct {
self.flatpak_command = null; self.flatpak_command = null;
} }
} }
// Close our PTY. We do this after killing our command because on
// macOS, close will block until all blocking operations read/write
// are done with it and our reader thread is probably still alive.
if (self.pty) |*pty| {
pty.deinit();
self.pty = null;
}
} }
/// Resize the pty subprocess. This is safe to call anytime. /// Resize the pty subprocess. This is safe to call anytime.