aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--cmd/hakurei/command.go8
-rw-r--r--cmd/hakurei/command_test.go6
-rw-r--r--hst/container.go7
-rw-r--r--internal/outcome/outcome.go9
-rw-r--r--internal/outcome/shim.go7
5 files changed, 34 insertions, 3 deletions
diff --git a/cmd/hakurei/command.go b/cmd/hakurei/command.go
index 76004d4f..f14945ad 100644
--- a/cmd/hakurei/command.go
+++ b/cmd/hakurei/command.go
@@ -106,7 +106,7 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
flagSchedPolicy string
flagSchedPriority int
- flagPrivateRuntime, flagPrivateTmpdir bool
+ flagNoWait, flagPrivateRuntime, flagPrivateTmpdir bool
flagWayland, flagX11, flagDBus, flagPipeWire, flagPulse bool
)
@@ -194,6 +194,10 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
},
}
+ if flagNoWait {
+ config.Container.AdoptWaitDelay = -1
+ }
+
if err := config.SchedPolicy.UnmarshalText(
[]byte(flagSchedPolicy),
); err != nil {
@@ -315,6 +319,8 @@ func buildCommand(ctx context.Context, msg message.Msg, early *earlyHardeningErr
"Scheduling policy to set for the container").
Flag(&flagSchedPriority, "priority", command.IntFlag(0),
"Scheduling priority to set for the container").
+ Flag(&flagNoWait, "no-wait", command.BoolFlag(false),
+ "Do not wait for lingering processes to terminate").
Flag(&flagPrivateRuntime, "private-runtime", command.BoolFlag(false),
"Do not share XDG_RUNTIME_DIR between containers under the same identity").
Flag(&flagPrivateTmpdir, "private-tmpdir", command.BoolFlag(false),
diff --git a/cmd/hakurei/command_test.go b/cmd/hakurei/command_test.go
index 059e18b1..49a1f9d4 100644
--- a/cmd/hakurei/command_test.go
+++ b/cmd/hakurei/command_test.go
@@ -39,8 +39,8 @@ commands:
[--dbus-system <value>] [--mpris] [--dbus-log]
[--id <value>] [-a <int>] [-g <value>] [-d <value>]
[-u <value>] [--policy <value>] [--priority <int>]
- [--private-runtime] [--private-tmpdir] [--wayland] [-X]
- [--dbus] [--pipewire] [--pulse] <command> [<args>]
+ [--no-wait] [--private-runtime] [--private-tmpdir]
+ [--wayland] [-X] [--dbus] [--pipewire] [--pulse] <command> [<args>]
flags:
-X Enable direct connection to X11
@@ -62,6 +62,8 @@ flags:
Reverse-DNS style Application identifier, leave empty to inherit instance identifier
-mpris
Allow owning MPRIS D-Bus path, has no effect if custom config is available
+ -no-wait
+ Do not wait for lingering processes to terminate
-pipewire
Enable connection to PipeWire via SecurityContext
-policy string
diff --git a/hst/container.go b/hst/container.go
index 824b0982..c4cd2712 100644
--- a/hst/container.go
+++ b/hst/container.go
@@ -141,6 +141,13 @@ type ContainerConfig struct {
// [WaitDelayDefault].
WaitDelay time.Duration `json:"wait_delay,omitempty"`
+ // Duration in nanoseconds to wait for lingering processes after the initial
+ // process terminates.
+ //
+ // Defaults to five seconds if zero or greater than five seconds. Values
+ // lesser than zero is equivalent to zero.
+ AdoptWaitDelay time.Duration `json:"adopt_wait_delay,omitempty"`
+
// Initial process environment variables.
Env map[string]string `json:"env"`
diff --git a/internal/outcome/outcome.go b/internal/outcome/outcome.go
index 414b421f..19ca9c7b 100644
--- a/internal/outcome/outcome.go
+++ b/internal/outcome/outcome.go
@@ -6,6 +6,7 @@ import (
"errors"
"maps"
"strconv"
+ "time"
"hakurei.app/check"
"hakurei.app/container"
@@ -125,6 +126,14 @@ func newOutcomeState(k syscallDispatcher, msg message.Msg, id *hst.ID, config *h
s.Shim.WaitDelay = s.Container.WaitDelay
}
+ if s.Container.AdoptWaitDelay > 5*time.Second {
+ s.Shim.AdoptWaitDelay = 5 * time.Second
+ } else if s.Container.AdoptWaitDelay < 0 {
+ s.Shim.AdoptWaitDelay = -1
+ } else {
+ s.Shim.AdoptWaitDelay = s.Container.AdoptWaitDelay
+ }
+
if s.Container.Flags&hst.FMapRealUID != 0 {
s.Mapuid, s.Mapgid = k.getuid(), k.getgid()
} else {
diff --git a/internal/outcome/shim.go b/internal/outcome/shim.go
index 6e039b65..2e7b0910 100644
--- a/internal/outcome/shim.go
+++ b/internal/outcome/shim.go
@@ -72,6 +72,12 @@ type shimParams struct {
// Limits are enforced on the priv side.
WaitDelay time.Duration
+ // Duration to wait after the initial process terminates before all
+ // lingering processes are killed.
+ //
+ // Limits are enforced on the priv side.
+ AdoptWaitDelay time.Duration
+
// Verbosity pass through from [message.Msg].
Verbose bool
@@ -286,6 +292,7 @@ func shimEntrypoint(k syscallDispatcher) {
// bounds and default enforced in finalise.go
z.WaitDelay = state.Shim.WaitDelay
+ z.AdoptWaitDelay = state.Shim.AdoptWaitDelay
if stateParams.pipewirePulsePath != nil {
zpw := container.NewCommand(ctx, msg, stateParams.pipewirePulsePath, pipewirePulseName)