diff --git a/daemon/errors.go b/daemon/errors.go index b85feaa2f1..0c65d6168c 100644 --- a/daemon/errors.go +++ b/daemon/errors.go @@ -132,7 +132,20 @@ func (e startInvalidConfigError) Error() string { func (e startInvalidConfigError) InvalidParameter() {} // Is this right??? -func translateContainerdStartErr(setExitCode func(int), err error) error { +// exitStatus is the exit-code as set by translateContainerdStartErr +type exitStatus = int + +const ( + exitEaccess exitStatus = 126 // container cmd can't be invoked (permission denied) + exitCmdNotFound exitStatus = 127 // container cmd not found/does not exist or invalid bind-mount + exitUnknown exitStatus = 128 // unknown error +) + +// translateContainerdStartErr converts the error returned by containerd +// when starting a container, and applies the corresponding exitStatus to the +// container. It returns an errdefs error (either errdefs.ErrInvalidParameter +// or errdefs.ErrUnknown). +func translateContainerdStartErr(setExitCode func(exitStatus), err error) error { errDesc := status.Convert(err).Message() contains := func(s1, s2 string) bool { return strings.Contains(strings.ToLower(s1), s2) @@ -140,24 +153,24 @@ func translateContainerdStartErr(setExitCode func(int), err error) error { var retErr = errdefs.Unknown(errors.New(errDesc)) // if we receive an internal error from the initial start of a container then lets // return it instead of entering the restart loop - // set to 127 for container cmd not found/does not exist) + // set to 127 for container cmd not found/does not exist. if contains(errDesc, "executable file not found") || contains(errDesc, "no such file or directory") || contains(errDesc, "system cannot find the file specified") || contains(errDesc, "failed to run runc create/exec call") { - setExitCode(127) + setExitCode(exitCmdNotFound) retErr = startInvalidConfigError(errDesc) } // set to 126 for container cmd can't be invoked errors if contains(errDesc, syscall.EACCES.Error()) { - setExitCode(126) + setExitCode(exitEaccess) retErr = startInvalidConfigError(errDesc) } // attempted to mount a file onto a directory, or a directory onto a file, maybe from user specified bind mounts if contains(errDesc, syscall.ENOTDIR.Error()) { errDesc += ": Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type" - setExitCode(127) + setExitCode(exitCmdNotFound) retErr = startInvalidConfigError(errDesc) } diff --git a/daemon/start.go b/daemon/start.go index 4463083009..318fa4c9e3 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -124,7 +124,7 @@ func (daemon *Daemon) containerStart(ctx context.Context, container *container.C container.SetError(retErr) // if no one else has set it, make sure we don't leave it at zero if container.ExitCode() == 0 { - container.SetExitCode(128) + container.SetExitCode(exitUnknown) } if err := container.CheckpointTo(daemon.containersReplica); err != nil { logrus.Errorf("%s: failed saving state on start failure: %v", container.ID, err)