aboutsummaryrefslogtreecommitdiffstats
path: root/widgets
diff options
context:
space:
mode:
authorTim Culverhouse <tim@timculverhouse.com>2022-09-29 17:14:59 -0500
committerRobin Jarry <robin@jarry.cc>2022-10-02 18:47:18 +0200
commit020279108c4234974a26580183ef60945c5bd5cb (patch)
treec6eb4e4cc2d94bd1e1a5209ff28743251a5beb7f /widgets
parent176a3d989f393988b3fd28ac14633c6716778f3b (diff)
downloadaerc-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.go46
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
}