Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support systemd socket activation #429

Merged
17 changes: 17 additions & 0 deletions hack/integration-systemd-socket.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh
set -e
if [ -z "$EXECED" ]
then
systemd-socket-activate -E EXECED=1 -l /tmp/activate.sock socat ACCEPT-FD:3 EXEC:"rootlesskit $0",nofork 2>/dev/null &
OUTPUT="$(curl --unix-socket /tmp/activate.sock http://localhost/hello 2>/dev/null)"
[ "$(printf 'Hello\n' )" = "$OUTPUT" ] || exit 1
else
[ "$LISTEN_FDS" = "1" ] || exit 1
read -r REQUEST
if [ "$(printf 'GET /hello HTTP/1.1\r\n')" = "$REQUEST" ]
then
printf 'HTTP/1.1 200 OK\r\nContent-Length: 6\r\n\r\nHello\n'
else
printf 'HTTP/1.1 400 Bad Request\r\nContent-Length: 5\r\n\r\nBad!\n'
fi
fi
18 changes: 18 additions & 0 deletions pkg/child/child.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,23 @@ var propagationStates = map[string]uintptr{
"rslave": uintptr(unix.MS_REC | unix.MS_SLAVE),
}

func setupFiles(cmd *exec.Cmd) {
// 0 1 and 2 are used for stdin. stdout, and stderr
const firstExtraFD = 3
systemdActivationFDs := 0
// check for systemd socket activation sockets
if v := os.Getenv("LISTEN_FDS"); v != "" {
if num, err := strconv.Atoi(v); err == nil {
systemdActivationFDs = num
cmd.ExtraFiles = make([]*os.File, systemdActivationFDs)
}
}
for fd := 0; fd < systemdActivationFDs; fd++ {
cmd.ExtraFiles[fd] = os.NewFile(uintptr(firstExtraFD + fd), "")
}
}


func createCmd(targetCmd []string) (*exec.Cmd, error) {
var args []string
if len(targetCmd) > 1 {
Expand All @@ -47,6 +64,7 @@ func createCmd(targetCmd []string) (*exec.Cmd, error) {
cmd.SysProcAttr = &syscall.SysProcAttr{
Pdeathsig: syscall.SIGKILL,
}
setupFiles(cmd)
return cmd, nil
}

Expand Down
24 changes: 22 additions & 2 deletions pkg/parent/parent.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,27 @@ func LockStateDir(stateDir string) (*flock.Flock, error) {
return lock, nil
}

func setupFilesAndEnv(cmd *exec.Cmd, readPipe *os.File, writePipe *os.File, envKey string) {
// 0 1 and 2 are used for stdin. stdout, and stderr
const firstExtraFD = 3
systemdActivationFDs := 0
// check for systemd socket activation sockets
if v := os.Getenv("LISTEN_FDS"); v != "" {
if num, err := strconv.Atoi(v); err == nil {
systemdActivationFDs = num
}
}
cmd.ExtraFiles = make([]*os.File, systemdActivationFDs + 2)
for fd := 0; fd < systemdActivationFDs; fd++ {
cmd.ExtraFiles[fd] = os.NewFile(uintptr(firstExtraFD + fd), "")
}
readIndex := systemdActivationFDs
writeIndex := readIndex + 1
cmd.ExtraFiles[readIndex] = readPipe
cmd.ExtraFiles[writeIndex] = writePipe
cmd.Env = append(os.Environ(), envKey+"="+strconv.Itoa(firstExtraFD+readIndex)+","+strconv.Itoa(firstExtraFD+writeIndex))
}

func Parent(opt Opt) error {
if err := checkPreflight(opt); err != nil {
return err
Expand Down Expand Up @@ -178,8 +199,7 @@ func Parent(opt Opt) error {
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.ExtraFiles = []*os.File{pipeR, pipe2W}
cmd.Env = append(os.Environ(), opt.PipeFDEnvKey+"=3,4")
setupFilesAndEnv(cmd, pipeR, pipe2W, opt.PipeFDEnvKey)
if opt.StateDirEnvKey != "" {
cmd.Env = append(cmd.Env, opt.StateDirEnvKey+"="+opt.StateDir)
}
Expand Down