diff options
| author | Ophestra <cat@gensokyo.uk> | 2025-12-15 12:32:05 +0900 |
|---|---|---|
| committer | Ophestra <cat@gensokyo.uk> | 2025-12-15 12:32:46 +0900 |
| commit | d0a3c6a2f3ac4da3921fa525cf1ee5ea7d68eb1c (patch) | |
| tree | 057761396cc629e36ed1f58237f95dd41278e916 /internal/outcome/shim.go | |
| parent | 0c0e3d6fc2bf37eef703e9295fc56ef2a2fc5808 (diff) | |
internal/outcome: optional shim private dir
This is a private work directory owned by the specific shim. Useful for sockets owned by this instance of the shim and requires no direct assistance from the priv-side process.
Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/outcome/shim.go')
| -rw-r--r-- | internal/outcome/shim.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/internal/outcome/shim.go b/internal/outcome/shim.go index bde79be3..59b1236c 100644 --- a/internal/outcome/shim.go +++ b/internal/outcome/shim.go @@ -14,6 +14,7 @@ import ( "time" "hakurei.app/container" + "hakurei.app/container/check" "hakurei.app/container/seccomp" "hakurei.app/container/std" "hakurei.app/hst" @@ -83,6 +84,55 @@ func Shim(msg message.Msg) { shimEntrypoint(direct{msg}) } +// A shimPrivate holds state of the private work directory owned by shim. +type shimPrivate struct { + // Path to directory if created. + pathname *check.Absolute + + k syscallDispatcher + id *stringPair[hst.ID] +} + +// unwrap returns the underlying pathname. +func (sp *shimPrivate) unwrap() *check.Absolute { + if sp.pathname == nil { + if a, err := check.NewAbs(sp.k.tempdir()); err != nil { + sp.k.fatal(err) + panic("unreachable") + } else { + pathname := a.Append(".hakurei-shim-" + sp.id.String()) + sp.k.getMsg().Verbosef("creating private work directory %q", pathname) + if err = sp.k.mkdir(pathname.String(), 0700); err != nil { + sp.k.fatal(err) + panic("unreachable") + } + sp.pathname = pathname + return sp.unwrap() + } + } else { + return sp.pathname + } +} + +// String returns the absolute pathname to the directory held by shimPrivate. +func (sp *shimPrivate) String() string { return sp.unwrap().String() } + +// destroy removes the directory held by shimPrivate. +func (sp *shimPrivate) destroy() { + defer func() { sp.pathname = nil }() + if sp.pathname != nil { + sp.k.getMsg().Verbosef("destroying private work directory %q", sp.pathname) + if err := sp.k.removeAll(sp.pathname.String()); err != nil { + sp.k.getMsg().GetLogger().Println(err) + } + } +} + +const ( + // shimPipeWireTimeout is the duration pipewire-pulse is allowed to run before its socket becomes available. + shimPipeWireTimeout = 5 * time.Second +) + func shimEntrypoint(k syscallDispatcher) { msg := k.getMsg() if msg == nil { @@ -208,6 +258,7 @@ func shimEntrypoint(k syscallDispatcher) { ctx, stop := k.notifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) cancelContainer.Store(&stop) + sp := shimPrivate{k: k, id: state.id} z := container.New(ctx, msg) z.Params = *stateParams.params z.Stdin, z.Stdout, z.Stderr = os.Stdin, os.Stdout, os.Stderr @@ -225,9 +276,11 @@ func shimEntrypoint(k syscallDispatcher) { } } printMessageError(f, "cannot start container:", err) + sp.destroy() k.exit(hst.ExitFailure) } if err := k.containerServe(z); err != nil { + sp.destroy() printMessageError(func(v ...any) { k.fatal(fmt.Sprintln(v...)) }, "cannot configure container:", err) } @@ -236,10 +289,13 @@ func shimEntrypoint(k syscallDispatcher) { seccomp.Preset(std.PresetStrict, seccomp.AllowMultiarch), seccomp.AllowMultiarch, ); err != nil { + sp.destroy() k.fatalf("cannot load syscall filter: %v", err) } if err := k.containerWait(z); err != nil { + sp.destroy() + var exitError *exec.ExitError if !errors.As(err, &exitError) { if errors.Is(err, context.Canceled) { @@ -250,4 +306,5 @@ func shimEntrypoint(k syscallDispatcher) { } k.exit(exitError.ExitCode()) } + sp.destroy() } |
