Supervise quarantined Remote input helpers and block uncertain replacement

This commit is contained in:
ak47 committed 2026-11-05 22:55:36 -05:00
1 parent 21d8904ee3
commit 5ab3efdfa7
5 files changed
+771 -4

No files matched your search

@@ -6,6 +6,8 @@ package xorg
import (
"bytes"
"context"
"errors"
"io"
"os"
"os/exec"
@@ -16,6 +18,68 @@ import (
"git.stormux.org/storm/cthulhu/internal/remoteinput"
)
func TestNativeRemoteKeyHelperSupervisor(t *testing.T) {
for _, cancellation := range []string{"explicit", "lease-context"} {
t.Run(cancellation, func(t *testing.T) {
remoteNativeThread(t)
path := os.Getenv("CTHULHU_REMOTE_INPUT_HELPER")
supervisor, err := remoteinput.NewSupervisor(path)
if err != nil {
t.Fatal(err)
}
probe := remoteNativeTarget(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
client, err := supervisor.Start(ctx, 71)
if err != nil {
t.Fatal(err)
}
defer func() { client.Cancel(); client.Wait() }()
codes := make([]uint16, 0, 2)
for _, name := range []string{"Shift_L", "Control_R"} {
code, err := probe.backend.Resolve(name)
if err != nil {
t.Fatal(err)
}
codes = append(codes, code)
if err := client.Apply(t.Context(), name, true); err != nil {
t.Fatal(err)
}
remoteNativeHeld(t, probe, code, true)
}
if _, err := supervisor.Start(t.Context(), 72); !errors.Is(err, remoteinput.ErrUnavailable) {
t.Fatal("active native helper replaced", err)
}
if cancellation == "explicit" {
client.Cancel()
} else {
cancel()
}
if err := client.Wait(); err != nil {
t.Fatal("native cleanup not confirmed", err)
}
for _, code := range codes {
remoteNativeHeld(t, probe, code, false)
}
replacement, err := supervisor.Start(t.Context(), 72)
if err != nil {
t.Fatal("confirmed cleanup blocked fresh owner", err)
}
defer func() { replacement.Cancel(); replacement.Wait() }()
client.Cancel()
if err := replacement.Apply(t.Context(), "Shift_L", true); err != nil {
t.Fatal("old owner cancellation affected replacement", err)
}
remoteNativeHeld(t, probe, codes[0], true)
replacement.Cancel()
if err := replacement.Wait(); err != nil {
t.Fatal(err)
}
remoteNativeHeld(t, probe, codes[0], false)
})
}
}
// The writer owns both write ends exclusively. The supervising test owns the
// helper process so it can observe cleanup and reap it after writer SIGKILL.
func TestNativeRemoteKeyControlWriter(t *testing.T) {