From 40865f977e4ae7b0f4141fdba6edc2d009ce67c7 Mon Sep 17 00:00:00 2001 From: makeworld Date: Wed, 22 Dec 2021 17:49:07 -0500 Subject: [PATCH] Don't leave zombie processes Fixes #219 --- CHANGELOG.md | 1 + display/download.go | 5 ++++- display/handlers.go | 16 ++++++++++------ sysopen/open_browser_darwin.go | 4 +++- sysopen/open_browser_unix.go | 4 +++- sysopen/open_browser_windows.go | 4 +++- webbrowser/open_browser_darwin.go | 4 +++- webbrowser/open_browser_unix.go | 8 ++++++-- webbrowser/open_browser_windows.go | 4 +++- 9 files changed, 36 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1f3469..27255ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Modal can't be closed when opening non-gemini text URLs from the commandline (#283, #284) +- External programs started by Amfora remain as zombie processes (#219) ## [1.9.2] - 2021-12-10 diff --git a/display/download.go b/display/download.go index 93800f0..fd08e14 100644 --- a/display/download.go +++ b/display/download.go @@ -191,6 +191,7 @@ func open(u string, resp *gemini.Response) { Error("File Opening Error", "Error executing custom command: "+err.Error()) return } + go proc.Wait() // Prevent zombies, see #219 Info("Opened with " + cmd[0]) return } @@ -214,11 +215,13 @@ func open(u string, resp *gemini.Response) { Info("Opened in default system viewer") } else { cmd := mediaHandler.Cmd - err := exec.Command(cmd[0], append(cmd[1:], path)...).Start() + proc := exec.Command(cmd[0], append(cmd[1:], path)...) + err := proc.Start() if err != nil { Error("File Opening Error", "Error executing custom command: "+err.Error()) return } + go proc.Wait() // Prevent zombies, see #219 Info("Opened with " + cmd[0]) } App.Draw() diff --git a/display/handlers.go b/display/handlers.go index 161d7e8..2fa95c9 100644 --- a/display/handlers.go +++ b/display/handlers.go @@ -48,16 +48,18 @@ func handleHTTP(u string, showInfo bool) bool { } // Custom command - var err error + var proc *exec.Cmd if len(config.HTTPCommand) > 1 { - err = exec.Command(config.HTTPCommand[0], append(config.HTTPCommand[1:], u)...).Start() + proc = exec.Command(config.HTTPCommand[0], append(config.HTTPCommand[1:], u)...) } else { - err = exec.Command(config.HTTPCommand[0], u).Start() + proc = exec.Command(config.HTTPCommand[0], u) } + err := proc.Start() if err != nil { Error("HTTP Error", "Error executing custom browser command: "+err.Error()) return false } + go proc.Wait() // Prevent zombies, see #219 Info("Opened with: " + config.HTTPCommand[0]) App.Draw() @@ -104,15 +106,17 @@ func handleOther(u string) { // Custom application command - var err error + var proc *exec.Cmd if len(handler) > 1 { - err = exec.Command(handler[0], append(handler[1:], u)...).Start() + proc = exec.Command(handler[0], append(handler[1:], u)...) } else { - err = exec.Command(handler[0], u).Start() + proc = exec.Command(handler[0], u) } + err := proc.Start() if err != nil { Error("URL Error", "Error executing custom command: "+err.Error()) } + go proc.Wait() // Prevent zombies, see #219 Info("Opened with: " + handler[0]) App.Draw() } diff --git a/sysopen/open_browser_darwin.go b/sysopen/open_browser_darwin.go index cf4320d..11d0f8a 100644 --- a/sysopen/open_browser_darwin.go +++ b/sysopen/open_browser_darwin.go @@ -7,9 +7,11 @@ import "os/exec" // Open opens `path` in default system viewer. func Open(path string) (string, error) { - err := exec.Command("open", path).Start() + proc := exec.Command("open", path) + err := proc.Start() if err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in default system viewer", nil } diff --git a/sysopen/open_browser_unix.go b/sysopen/open_browser_unix.go index 80c0ffc..76e0ab9 100644 --- a/sysopen/open_browser_unix.go +++ b/sysopen/open_browser_unix.go @@ -25,9 +25,11 @@ func Open(path string) (string, error) { case xdgOpenNotFoundErr == nil: // Use start rather than run or output in order // to make application run in background. - if err := exec.Command(xdgOpenPath, path).Start(); err != nil { + proc := exec.Command(xdgOpenPath, path) + if err := proc.Start(); err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in default system viewer", nil default: return "", fmt.Errorf("could not determine default system viewer. " + diff --git a/sysopen/open_browser_windows.go b/sysopen/open_browser_windows.go index ecadd01..b2323ff 100644 --- a/sysopen/open_browser_windows.go +++ b/sysopen/open_browser_windows.go @@ -8,9 +8,11 @@ import "os/exec" // Open opens `path` in default system vierwer. func Open(path string) (string, error) { - err := exec.Command("rundll32", "url.dll,FileProtocolHandler", path).Start() + proc := exec.Command("rundll32", "url.dll,FileProtocolHandler", path) + err := proc.Start() if err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in default system viewer", nil } diff --git a/webbrowser/open_browser_darwin.go b/webbrowser/open_browser_darwin.go index 29ffb3d..fd393a4 100644 --- a/webbrowser/open_browser_darwin.go +++ b/webbrowser/open_browser_darwin.go @@ -7,9 +7,11 @@ import "os/exec" // Open opens `url` in default system browser. func Open(url string) (string, error) { - err := exec.Command("open", url).Start() + proc := exec.Command("open", url) + err := proc.Start() if err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in system default web browser", nil } diff --git a/webbrowser/open_browser_unix.go b/webbrowser/open_browser_unix.go index 71fcf7d..14d01eb 100644 --- a/webbrowser/open_browser_unix.go +++ b/webbrowser/open_browser_unix.go @@ -34,14 +34,18 @@ func Open(url string) (string, error) { case xdgOpenNotFoundErr == nil: // Prefer xdg-open over $BROWSER // Use start rather than run or output in order // to make browser running in background. - if err := exec.Command(xdgOpenPath, url).Start(); err != nil { + proc := exec.Command(xdgOpenPath, url) + if err := proc.Start(); err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in system default web browser", nil case envBrowser != "": - if err := exec.Command(envBrowser, url).Start(); err != nil { + proc := exec.Command(envBrowser, url) + if err := proc.Start(); err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in system default web browser", nil default: return "", fmt.Errorf("could not determine system browser") diff --git a/webbrowser/open_browser_windows.go b/webbrowser/open_browser_windows.go index 8137c0d..4cff6a8 100644 --- a/webbrowser/open_browser_windows.go +++ b/webbrowser/open_browser_windows.go @@ -8,9 +8,11 @@ import "os/exec" // Open opens `url` in default system browser. func Open(url string) (string, error) { - err := exec.Command("rundll32", "url.dll,FileProtocolHandler", url).Start() + proc := exec.Command("rundll32", "url.dll,FileProtocolHandler", url) + err := proc.Start() if err != nil { return "", err } + go proc.Wait() // Prevent zombies, see #219 return "Opened in system default web browser", nil }