mirror of
https://github.com/opencontainers/runc.git
synced 2025-11-03 09:51:06 +08:00
*: introduce pidfd-socket flag
The container manager like containerd-shim can't use cgroup.kill feature or freeze all the processes in cgroup to terminate the exec init process. It's unsafe to call kill(2) since the pid can be recycled. It's good to provide the pidfd of init process through the pidfd-socket. It's similar to the console-socket. With the pidfd, the container manager like containerd-shim can send the signal to target process safely. And for the standard init process, we can have polling support to get exit event instead of blocking on wait4. Signed-off-by: Wei Fu <fuweid89@gmail.com>
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/opencontainers/runc/libcontainer"
|
||||
"github.com/opencontainers/runc/libcontainer/configs"
|
||||
"github.com/opencontainers/runc/libcontainer/specconv"
|
||||
"github.com/opencontainers/runc/libcontainer/system/kernelversion"
|
||||
"github.com/opencontainers/runc/libcontainer/utils"
|
||||
)
|
||||
|
||||
@@ -199,6 +200,7 @@ type runner struct {
|
||||
preserveFDs int
|
||||
pidFile string
|
||||
consoleSocket string
|
||||
pidfdSocket string
|
||||
container *libcontainer.Container
|
||||
action CtAct
|
||||
notifySocket *notifySocket
|
||||
@@ -255,6 +257,14 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
||||
}
|
||||
defer tty.Close()
|
||||
|
||||
if r.pidfdSocket != "" {
|
||||
connClose, err := setupPidfdSocket(process, r.pidfdSocket)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer connClose()
|
||||
}
|
||||
|
||||
switch r.action {
|
||||
case CT_ACT_CREATE:
|
||||
err = r.container.Start(process)
|
||||
@@ -390,6 +400,7 @@ func startContainer(context *cli.Context, action CtAct, criuOpts *libcontainer.C
|
||||
listenFDs: listenFDs,
|
||||
notifySocket: notifySocket,
|
||||
consoleSocket: context.String("console-socket"),
|
||||
pidfdSocket: context.String("pidfd-socket"),
|
||||
detach: context.Bool("detach"),
|
||||
pidFile: context.String("pid-file"),
|
||||
preserveFDs: context.Int("preserve-fds"),
|
||||
@@ -399,3 +410,36 @@ func startContainer(context *cli.Context, action CtAct, criuOpts *libcontainer.C
|
||||
}
|
||||
return r.run(spec.Process)
|
||||
}
|
||||
|
||||
func setupPidfdSocket(process *libcontainer.Process, sockpath string) (_clean func(), _ error) {
|
||||
linux530 := kernelversion.KernelVersion{Kernel: 5, Major: 3}
|
||||
ok, err := kernelversion.GreaterEqualThan(linux530)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("--pidfd-socket requires >= v5.3 kernel")
|
||||
}
|
||||
|
||||
conn, err := net.Dial("unix", sockpath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to dail %s: %w", sockpath, err)
|
||||
}
|
||||
|
||||
uc, ok := conn.(*net.UnixConn)
|
||||
if !ok {
|
||||
conn.Close()
|
||||
return nil, errors.New("failed to cast to UnixConn")
|
||||
}
|
||||
|
||||
socket, err := uc.File()
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return nil, fmt.Errorf("failed to dup socket: %w", err)
|
||||
}
|
||||
|
||||
process.PidfdSocket = socket
|
||||
return func() {
|
||||
conn.Close()
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user