commit 4f250f04cf94416445369fb917ae3b6d38ad2c78
parent 34d9312ab26a5eaa3e089c1e90f7faa447de8211
Author: Sean Enck <sean@ttypty.com>
Date: Sun, 29 Jun 2025 22:23:42 -0400
fixing some clipboard manager components
Diffstat:
3 files changed, 62 insertions(+), 6 deletions(-)
diff --git a/internal/config/vars.go b/internal/config/vars.go
@@ -51,6 +51,7 @@ var (
description: "Set the pidfile for clipboard management",
}),
allowed: []string{fileExample},
+ flags: []stringsFlags{canExpandFlag},
},
})
// EnvJSONHashLength handles the hashing output length
diff --git a/internal/platform/clipmanager.go b/internal/platform/clipmanager.go
@@ -6,7 +6,9 @@ import (
"fmt"
"os"
"os/exec"
+ "strconv"
"strings"
+ "syscall"
"time"
"git.sr.ht/~enckse/lockbox/internal/app/commands"
@@ -23,6 +25,7 @@ type (
Copy(Clipboard, string)
Sleep()
Loader() ClipboardLoader
+ Checkpid(int) error
}
// DefaultClipboardDaemon is the default functioning daemon
DefaultClipboardDaemon struct{}
@@ -68,6 +71,15 @@ func (d DefaultClipboardDaemon) Loader() ClipboardLoader {
return DefaultClipboardLoader{Full: true}
}
+// Checkpid will check if a pid is still active
+func (d DefaultClipboardDaemon) Checkpid(pid int) error {
+ process, err := os.FindProcess(pid)
+ if err != nil {
+ return err
+ }
+ return process.Signal(syscall.Signal(0))
+}
+
// ClipboardManager handles the daemon runner
func ClipboardManager(daemon bool, manager ClipboardDaemon) error {
if manager == nil {
@@ -80,7 +92,28 @@ func ClipboardManager(daemon bool, manager ClipboardDaemon) error {
if clipboard.PIDFile == "" {
return errors.New("pidfile is unset")
}
+ getProcess := func() (string, error) {
+ b, err := manager.ReadFile(clipboard.PIDFile)
+ if err != nil {
+ return "", err
+ }
+ val := strings.TrimSpace(string(b))
+ return val, nil
+ }
if !daemon {
+ if PathExists(clipboard.PIDFile) {
+ p, err := getProcess()
+ if err != nil {
+ return err
+ }
+ pid, err := strconv.Atoi(p)
+ if err != nil {
+ return err
+ }
+ if err := manager.Checkpid(pid); err == nil {
+ return nil
+ }
+ }
return manager.Start(commands.Executable, commands.ClipManagerDaemon)
}
paste, pasteArgs, err := clipboard.Args(false)
@@ -104,12 +137,8 @@ func ClipboardManager(daemon bool, manager ClipboardDaemon) error {
}
pid := strings.TrimSpace(fmt.Sprintf("%d", manager.Getpid()))
isCurrentProcess := func() (bool, error) {
- b, err := manager.ReadFile(clipboard.PIDFile)
- if err != nil {
- return false, err
- }
- val := strings.TrimSpace(string(b))
- return val == pid, nil
+ val, err := getProcess()
+ return val == pid, err
}
manager.WriteFile(clipboard.PIDFile, pid)
var errs []error
diff --git a/internal/platform/clipmanager_test.go b/internal/platform/clipmanager_test.go
@@ -3,6 +3,8 @@ package platform_test
import (
"errors"
"fmt"
+ "os"
+ "path/filepath"
"strings"
"testing"
@@ -62,6 +64,10 @@ func (d *mock) Loader() platform.ClipboardLoader {
return mockLoader{name: "linux", runtime: "linux"}
}
+func (d *mock) Checkpid(_ int) error {
+ return d.err
+}
+
func TestErrors(t *testing.T) {
store.Clear()
defer store.Clear()
@@ -92,6 +98,26 @@ func TestStart(t *testing.T) {
if m.cmd != "lb" || fmt.Sprintf("%v", m.args) != "[clipmgrd]" {
t.Errorf("invalid calls: %s %v", m.cmd, m.args)
}
+ pidFile := "testdata"
+ os.MkdirAll(pidFile, 0o755)
+ pidFile = filepath.Join("testdata", "pidfile")
+ store.SetString("LOCKBOX_CLIP_PIDFILE", pidFile)
+ os.WriteFile(pidFile, []byte("123"), 0o644)
+ defer os.Remove(pidFile)
+ m.cmd = ""
+ m.args = []string{}
+ if err := platform.ClipboardManager(false, m); err == nil || !strings.Contains(err.Error(), "Atoi") {
+ t.Errorf("invalid error: %v", err)
+ }
+ m.data = "1234"
+ m.cmd = ""
+ m.args = []string{}
+ if err := platform.ClipboardManager(false, m); err != nil {
+ t.Errorf("invalid error: %v", err)
+ }
+ if m.cmd != "" || fmt.Sprintf("%v", m.args) != "[]" {
+ t.Errorf("invalid calls: %s %v", m.cmd, m.args)
+ }
}
func TestPIDMismatch(t *testing.T) {