container: enter init path early
Test / Create distribution (push) Successful in 59s
Test / Sandbox (push) Successful in 3m0s
Test / Hakurei (push) Successful in 4m48s
Test / Sandbox (race detector) (push) Successful in 6m6s
Test / Hakurei (race detector) (push) Successful in 7m32s
Test / ShareFS (push) Successful in 7m54s
Test / Flake checks (push) Successful in 1m19s

There is generally no use case where any setup is required before init, and requiring the explicit function call is error-prone and unnecessary. It also causes trouble with packages using a similar trick. This change moves argv0 check early and makes it an import side effect. The stub will be removed in v0.5.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
cat
2026-08-25 14:53:29 +09:00
parent ac7abbbe3f
commit 1c3761bb53
22 changed files with 32 additions and 72 deletions
+30 -10
View File
@@ -2,6 +2,7 @@ package container
import (
"context"
"encoding/gob"
"errors"
"fmt"
"log"
@@ -130,7 +131,7 @@ type initParams struct {
Verbose bool
}
// Init is called by [TryArgv0] if the current process is the container init.
// Init is called if the current process is the container init.
func Init(msg message.Msg) { initEntrypoint(direct{}, msg) }
func initEntrypoint(k syscallDispatcher, msg message.Msg) {
@@ -642,18 +643,37 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
// initName is the prefix used by log.std in the init process.
const initName = "init"
// TryArgv0 calls [Init] if the last element of argv0 is "init".
// If a nil msg is passed, the system logger is used instead.
func TryArgv0(msg message.Msg) {
if msg == nil {
log.SetPrefix(initName + ": ")
log.SetFlags(0)
msg = message.New(log.Default())
var _ = func() struct{} {
for _, v := range []any{
(*AutoEtcOp)(nil),
(*AutoRootOp)(nil),
(*BindMountOp)(nil),
(*DaemonOp)(nil),
(*MkdirOp)(nil),
(*MountDevOp)(nil),
(*MountOverlayOp)(nil),
(*MountProcOp)(nil),
(*MountTmpfsOp)(nil),
(*RemountOp)(nil),
(*SymlinkOp)(nil),
(*TmpfileOp)(nil),
} {
gob.Register(v)
}
if len(os.Args) > 0 && filepath.Base(os.Args[0]) == initName {
if len(os.Args) == 1 && filepath.Base(os.Args[0]) == initName {
log.SetPrefix(initName + ": ")
log.SetFlags(0)
msg := message.New(log.Default())
Init(msg)
msg.BeforeExit()
os.Exit(0)
}
}
return struct{}{}
}()
// TryArgv0 is a noop.
//
// Deprecated: init is now implemented as an import side effect.
func TryArgv0(_ message.Msg) {}