diff options
author | Koni Marti <koni.marti@gmail.com> | 2022-05-23 22:16:13 +0200 |
---|---|---|
committer | Robin Jarry <robin@jarry.cc> | 2022-05-23 22:31:15 +0200 |
commit | 1bac87e80414f8e787c54f7f4cd2a3920aa1a095 (patch) | |
tree | 0df1fb7d749b2d91b15cf1a45d1d9560c0014100 | |
parent | f4d4e2b4e1733c1c5257a54e2fa9de2a2a2f5f28 (diff) | |
download | aerc-1bac87e80414f8e787c54f7f4cd2a3920aa1a095.zip |
terminal: fix race when closing a terminal
Fix race when closing a terminal. The race appears as a nil pointer
dereference panic in pty.StartWithAttrs when trying to access the
provided term.cmd variable.
Before calling pty.StartwithAttrs in the Terminal.Draw function,
term.cmd is checked for nil. Terminal.Close must be called concurrently
right after this check and before/while entering pty.StartWithAttrs.
This can be avoided with a mutex.
Link: https://github.com/creack/pty/issues/146
Link: https://lists.sr.ht/~rjarry/aerc-devel/%3CCJ2I45HMOTGD.2J1QMEJ4T1E3N%40t450.arielp.com%3E#%3CCJ3D069RCTXL.3VEZ7JIGFHOHK@Archetype%3E
Fixes: https://todo.sr.ht/~rjarry/aerc/38
Signed-off-by: Koni Marti <koni.marti@gmail.com>
Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r-- | widgets/terminal.go | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/widgets/terminal.go b/widgets/terminal.go index 5baaec2..cd265f6 100644 --- a/widgets/terminal.go +++ b/widgets/terminal.go @@ -108,6 +108,7 @@ type Terminal struct { damageMutex sync.Mutex writeMutex sync.Mutex readMutex sync.Mutex + closeMutex sync.Mutex OnClose func(err error) OnEvent func(event tcell.Event) bool @@ -178,6 +179,9 @@ func (term *Terminal) flushTerminal() { } func (term *Terminal) Close(err error) { + term.closeMutex.Lock() + defer term.closeMutex.Unlock() + if term.closed { return } @@ -199,6 +203,9 @@ func (term *Terminal) Close(err error) { } func (term *Terminal) Destroy() { + term.closeMutex.Lock() + defer term.closeMutex.Unlock() + if term.destroyed { return } @@ -228,6 +235,9 @@ func (term *Terminal) invalidate() { } func (term *Terminal) Draw(ctx *ui.Context) { + term.closeMutex.Lock() + defer term.closeMutex.Unlock() + if term.destroyed { return } |