From 4188d5946b1f6ac9090a2a49a342d361762a7298 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Thu, 21 May 2026 08:49:36 +0200 Subject: [PATCH] execute: transparent per-session mount recovery on stale FUSE --- pkg/tools/execute/code.go | 1 + pkg/tools/execute/server.go | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/pkg/tools/execute/code.go b/pkg/tools/execute/code.go index 0b729c9..5b22a39 100644 --- a/pkg/tools/execute/code.go +++ b/pkg/tools/execute/code.go @@ -107,6 +107,7 @@ var languagePatterns = map[string][]*regexp.Regexp{ // Dispatch routes a named execute tool call. func (e *Server) Dispatch(ctx context.Context, name string, args json.RawMessage) (string, error) { + e.remountIfStale() if len(e.allowExecutors) > 0 && !e.allowExecutors[name] { return "", fmt.Errorf("executor %q not permitted in this agent context", name) } diff --git a/pkg/tools/execute/server.go b/pkg/tools/execute/server.go index 8f7c9b5..ddde08a 100644 --- a/pkg/tools/execute/server.go +++ b/pkg/tools/execute/server.go @@ -403,6 +403,31 @@ func (e *Server) startMount(sessionID string) { e.envExtra["OLLIE"] = mnt } +// remountIfStale checks the per-session FUSE mount health and re-establishes it if broken. +// Must be called without envMu held. +func (e *Server) remountIfStale() { + e.envMu.RLock() + mnt := e.mountPath + proc := e.mountProc + e.envMu.RUnlock() + if mnt == "" || proc == nil { + return + } + if _, err := os.Stat(filepath.Join(mnt, "s")); err == nil { + return + } + // Mount is stale — tear down and restart. + e.envMu.Lock() + defer e.envMu.Unlock() + exec.Command("fusermount", "-u", e.mountPath).Run() //nolint:errcheck + syscall.Kill(e.mountProc.Pid, syscall.SIGKILL) //nolint:errcheck + e.mountProc = nil + e.mountPath = "" + if uname := e.envExtra["OLLIE_UNAME"]; uname != "" { + e.startMount(uname) + } +} + // Close tears down the per-session FUSE mount. func (e *Server) Close() { e.envMu.Lock()