diff options
author | Tim Culverhouse <tim@timculverhouse.com> | 2022-09-29 17:14:59 -0500 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-10-02 18:47:18 +0200 |
commit | 020279108c4234974a26580183ef60945c5bd5cb (patch) | |
tree | c6eb4e4cc2d94bd1e1a5209ff28743251a5beb7f /widgets | |
parent | 176a3d989f393988b3fd28ac14633c6716778f3b (diff) | |
download | aerc-020279108c4234974a26580183ef60945c5bd5cb.tar.gz |
terminal: fix race conditions on access to cmd
Upgrade tcell-term to v0.2.0
Use Start method from tcell-term. This prevents aerc from needing to
wait until the command has started to continue. The tcell-term start
method blocks until the command is started, similar to cmd.Start. By
doing so, we prevent a race condition between aerc and tcell-term on
access to cmd.Process.
Remove cleanup of cmd, this is all already handled by tcell-term when
Close is called.
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
Acked-by: Robin Jarry <robin@jarry.cc>
Diffstat (limited to 'widgets')
-rw-r--r-- | widgets/terminal.go | 46 |
1 files changed, 11 insertions, 35 deletions
diff --git a/widgets/terminal.go b/widgets/terminal.go index cd90ed7a..894bdf09 100644 --- a/widgets/terminal.go +++ b/widgets/terminal.go @@ -42,24 +42,9 @@ func (term *Terminal) Close(err error) { if term.closed { return } - // Stop receiving events - term.vterm.Unwatch(term) - if term.cmd != nil && term.cmd.Process != nil { - err := term.cmd.Process.Kill() - if err != nil { - logging.Warnf("failed to kill process: %v", err) - } - // Race condition here, check if cmd exists. If process exits - // fast, this could by nil and panic - if term.cmd != nil { - err = term.cmd.Wait() - } - if err != nil { - logging.Warnf("failed for wait for process to terminate: %v", err) - } - term.cmd = nil - } if term.vterm != nil { + // Stop receiving events + term.vterm.Unwatch(term) term.vterm.Close() } if !term.closed && term.OnClose != nil { @@ -96,25 +81,14 @@ func (term *Terminal) Draw(ctx *ui.Context) { term.ctx = ctx // gross term.vterm.SetView(ctx.View()) if !term.running && !term.closed && term.cmd != nil { - go func() { - defer logging.PanicHandler() - term.vterm.Watch(term) - attr := &syscall.SysProcAttr{Setsid: true, Setctty: true, Ctty: 1} - if err := term.vterm.RunWithAttrs(term.cmd, attr); err != nil { - logging.Errorf("error running terminal: %w", err) - term.Close(err) - term.running = false - return - } - term.running = false - term.Close(nil) - }() - for { - if term.cmd.Process != nil { - term.running = true - break - } + term.vterm.Watch(term) + attr := &syscall.SysProcAttr{Setsid: true, Setctty: true, Ctty: 1} + if err := term.vterm.StartWithAttrs(term.cmd, attr); err != nil { + logging.Errorf("error running terminal: %w", err) + term.Close(err) + return } + term.running = true if term.OnStart != nil { term.OnStart() } @@ -193,6 +167,8 @@ func (term *Terminal) HandleEvent(ev tcell.Event) bool { if term.OnTitle != nil { term.OnTitle(ev.Title()) } + case *tcellterm.EventClosed: + term.Close(nil) } return false } |