container/init: unwrap descriptive fatal error
All checks were successful
Test / Create distribution (push) Successful in 33s
Test / Sandbox (push) Successful in 2m12s
Test / Hakurei (push) Successful in 3m6s
Test / Hpkg (push) Successful in 4m0s
Test / Hakurei (race detector) (push) Successful in 5m20s
Test / Sandbox (race detector) (push) Successful in 2m3s
Test / Flake checks (push) Successful in 1m27s

These errors are printed with a descriptive message prefixed to them, so it is more readable to expose the underlying errno.

Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
Ophestra 2025-10-09 22:04:35 +09:00
parent 87b5c30ef6
commit a941ac025f
Signed by: cat
SSH Key Fingerprint: SHA256:gQ67O0enBZ7UdZypgtspB2FDM1g3GVw8nX0XSdcFw8Q
3 changed files with 16 additions and 5 deletions

View File

@ -59,6 +59,7 @@ func messagePrefixP[V any, T interface {
return zeroString, false
}
// MountError wraps errors returned by syscall.Mount.
type MountError struct {
Source, Target, Fstype string
@ -74,6 +75,7 @@ func (e *MountError) Unwrap() error {
return e.Errno
}
func (e *MountError) Message() string { return "cannot " + e.Error() }
func (e *MountError) Error() string {
if e.Flags&syscall.MS_BIND != 0 {
if e.Flags&syscall.MS_REMOUNT != 0 {
@ -90,6 +92,15 @@ func (e *MountError) Error() string {
return "mount " + e.Target + ": " + e.Errno.Error()
}
// optionalErrorUnwrap calls [errors.Unwrap] and returns the resulting value
// if it is not nil, or the original value if it is.
func optionalErrorUnwrap(err error) error {
if underlyingErr := errors.Unwrap(err); underlyingErr != nil {
return underlyingErr
}
return err
}
// errnoFallback returns the concrete errno from an error, or a [os.PathError] fallback.
func errnoFallback(op, path string, err error) (syscall.Errno, *os.PathError) {
var errno syscall.Errno

View File

@ -178,7 +178,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
lastcap := k.lastcap(msg)
if err := k.mount(zeroString, fhs.Root, zeroString, MS_SILENT|MS_SLAVE|MS_REC, zeroString); err != nil {
k.fatalf(msg, "cannot make / rslave: %v", err)
k.fatalf(msg, "cannot make / rslave: %v", optionalErrorUnwrap(err))
}
state := &setupState{Params: &params.Params, Msg: msg}
@ -202,7 +202,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
}
if err := k.mount(SourceTmpfsRootfs, intermediateHostPath, FstypeTmpfs, MS_NODEV|MS_NOSUID, zeroString); err != nil {
k.fatalf(msg, "cannot mount intermediate root: %v", err)
k.fatalf(msg, "cannot mount intermediate root: %v", optionalErrorUnwrap(err))
}
if err := k.chdir(intermediateHostPath); err != nil {
k.fatalf(msg, "cannot enter intermediate host path: %v", err)
@ -212,7 +212,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
k.fatalf(msg, "%v", err)
}
if err := k.mount(sysrootDir, sysrootDir, zeroString, MS_SILENT|MS_BIND|MS_REC, zeroString); err != nil {
k.fatalf(msg, "cannot bind sysroot: %v", err)
k.fatalf(msg, "cannot bind sysroot: %v", optionalErrorUnwrap(err))
}
if err := k.mkdir(hostDir, 0755); err != nil {
@ -246,7 +246,7 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) {
// setup requiring host root complete at this point
if err := k.mount(hostDir, hostDir, zeroString, MS_SILENT|MS_REC|MS_PRIVATE, zeroString); err != nil {
k.fatalf(msg, "cannot make host root rprivate: %v", err)
k.fatalf(msg, "cannot make host root rprivate: %v", optionalErrorUnwrap(err))
}
if err := k.unmount(hostDir, MNT_DETACH); err != nil {
k.fatalf(msg, "cannot unmount host root: %v", err)

View File

@ -31,7 +31,7 @@ func Receive(key string, e any, fdp *uintptr) (func() error, error) {
return nil, ErrReceiveEnv
} else {
if fd, err := strconv.Atoi(s); err != nil {
return nil, errors.Unwrap(err)
return nil, optionalErrorUnwrap(err)
} else {
setup = os.NewFile(uintptr(fd), "setup")
if setup == nil {