aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Cox <me@jasoncarloscox.com>2024-02-22 20:25:14 -0500
committerRobin Jarry <robin@jarry.cc>2024-04-13 21:46:33 +0200
commit8312b46f144cc1bcf5b6838854df2a9b167c1c3a (patch)
tree9a1955f37f5ed3f540ee00419d75a727e2ae299e
parent941e2e9e7de058f9e6e10efab1ece8be4188468e (diff)
downloadaerc-8312b46f144cc1bcf5b6838854df2a9b167c1c3a.tar.gz
aerc-8312b46f144cc1bcf5b6838854df2a9b167c1c3a.zip
ipc: improve error handling
Detect error responses in addition to errors connecting, sending the request, and receiving the response. If an error occurs when retrying the IPC call, keep the new aerc instance running and simply show the error. We already know (due to the initial failed IPC call) that no other aerc instance is running. Keeping the new instance open also improves the visibility of the error in some cases, such as when clicking on a malformed mailto link causes a new aerc instance to open. Signed-off-by: Jason Cox <me@jasoncarloscox.com> Acked-by: Robin Jarry <robin@jarry.cc>
-rw-r--r--lib/ipc/receive.go2
-rw-r--r--lib/ipc/send.go19
-rw-r--r--main.go31
3 files changed, 28 insertions, 24 deletions
diff --git a/lib/ipc/receive.go b/lib/ipc/receive.go
index 79618f50..4f6258ad 100644
--- a/lib/ipc/receive.go
+++ b/lib/ipc/receive.go
@@ -27,7 +27,7 @@ type AercServer struct {
func StartServer(handler Handler, startup context.Context) (*AercServer, error) {
sockpath := xdg.RuntimePath("aerc.sock")
// remove the socket if it is not connected to a session
- if err := ConnectAndExec(nil); err != nil {
+ if _, err := ConnectAndExec(nil); err != nil {
os.Remove(sockpath)
}
log.Debugf("Starting Unix server: %s", sockpath)
diff --git a/lib/ipc/send.go b/lib/ipc/send.go
index fbe67413..d5138bf8 100644
--- a/lib/ipc/send.go
+++ b/lib/ipc/send.go
@@ -9,36 +9,31 @@ import (
"git.sr.ht/~rjarry/aerc/lib/xdg"
)
-func ConnectAndExec(args []string) error {
+func ConnectAndExec(args []string) (*Response, error) {
sockpath := xdg.RuntimePath("aerc.sock")
conn, err := net.Dial("unix", sockpath)
if err != nil {
- return err
+ return nil, err
}
defer conn.Close()
req, err := (&Request{Arguments: args}).Encode()
if err != nil {
- return fmt.Errorf("failed to encode request: %w", err)
+ return nil, fmt.Errorf("failed to encode request: %w", err)
}
_, err = conn.Write(append(req, '\n'))
if err != nil {
- return fmt.Errorf("failed to send message: %w", err)
+ return nil, fmt.Errorf("failed to send message: %w", err)
}
scanner := bufio.NewScanner(conn)
if !scanner.Scan() {
- return errors.New("No response from server")
+ return nil, errors.New("No response from server")
}
resp, err := DecodeResponse(scanner.Bytes())
if err != nil {
- return err
+ return nil, err
}
- // TODO: handle this in a more elegant manner
- if resp.Error != "" {
- fmt.Println("result: ", resp.Error)
- }
-
- return nil
+ return resp, nil
}
diff --git a/main.go b/main.go
index 85538311..f73ac1e9 100644
--- a/main.go
+++ b/main.go
@@ -158,14 +158,16 @@ func main() {
if err != nil {
die("%s", err)
}
- retryExec := false
+
if len(opts.Command) > 0 {
- err := ipc.ConnectAndExec(opts.Command)
+ response, err := ipc.ConnectAndExec(opts.Command)
if err == nil {
+ if response.Error != "" {
+ fmt.Printf("response: %s\n", response.Error)
+ }
return // other aerc instance takes over
}
// continue with setting up a new aerc instance and retry after init
- retryExec = true
}
err = config.LoadConfigFromFile(
@@ -212,18 +214,25 @@ func main() {
enableIpc := func() {
startupDone()
- if !retryExec {
+ if len(opts.Command) == 0 {
return
}
// retry execution
- err := ipc.ConnectAndExec(opts.Command)
+ response, err := ipc.ConnectAndExec(opts.Command)
+ var errMsg string
if err != nil {
- fmt.Fprintf(os.Stderr, "Failed to communicate to aerc: %v\n", err)
- err = app.CloseBackends()
- if err != nil {
- log.Warnf("failed to close backends: %v", err)
- }
- os.Exit(1)
+ errMsg = err.Error()
+ } else {
+ errMsg = response.Error
+ }
+
+ if errMsg != "" {
+ // no other aerc instance is running, so let
+ // this one stay running but show the error
+ errMsg = fmt.Sprintf("Startup command (%s) failed: %s\n",
+ strings.Join(opts.Command, " "), errMsg)
+ log.Errorf(errMsg)
+ app.PushError(errMsg)
}
}