mirror of
https://github.com/clearlinux/rkt.git
synced 2026-09-06 05:41:50 +00:00
stage1: remove --pid-file patches from systemd-nspawn
Instead of asking systemd-nspawn to write its "pid" file, rkt can write the parent pid "ppid". Then, update getPID() to get the pid file from /proc/$ppid/task/$ppid/children. In this way, we don't need to patch systemd-nspawn. getPID() is able to read both the "pid" file and the "ppid" file, in order to work with alternative stage1s which choose to implement one or the other method. coreos/rkt#910
This commit is contained in:
+90
-3
@@ -19,10 +19,13 @@ package main
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -731,16 +734,97 @@ func (p *pod) getState() string {
|
||||
return state
|
||||
}
|
||||
|
||||
type ErrChildNotReady struct {
|
||||
}
|
||||
|
||||
func (e ErrChildNotReady) Error() string {
|
||||
return fmt.Sprintf("Child not ready")
|
||||
}
|
||||
|
||||
// Returns the pid of the child, or ErrChildNotReady if not ready
|
||||
func getChildPID(ppid int) (int, error) {
|
||||
var pid int
|
||||
|
||||
// If possible, get the child in O(1). Fallback on O(n) when the kernel does not have
|
||||
// either CONFIG_PROC_CHILDREN or CONFIG_CHECKPOINT_RESTORE
|
||||
_, err := os.Stat("/proc/1/task/1/children")
|
||||
if err == nil {
|
||||
b, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/task/%d/children", ppid, ppid))
|
||||
if err == nil {
|
||||
children := strings.SplitN(string(b), " ", 2)
|
||||
if len(children) == 2 && children[1] != "" {
|
||||
return -1, fmt.Errorf("too many children of pid %d", ppid)
|
||||
}
|
||||
if _, err := fmt.Sscanf(children[0], "%d ", &pid); err == nil {
|
||||
return pid, nil
|
||||
}
|
||||
}
|
||||
return -1, ErrChildNotReady{}
|
||||
}
|
||||
|
||||
// Fallback on the slower method
|
||||
fdir, err := os.Open(`/proc`)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
defer fdir.Close()
|
||||
|
||||
for {
|
||||
fi, err := fdir.Readdir(1)
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
var pid64 int64
|
||||
if pid64, err = strconv.ParseInt(fi[0].Name(), 10, 0); err != nil {
|
||||
continue
|
||||
}
|
||||
filename := fmt.Sprintf("/proc/%d/stat", pid64)
|
||||
statBytes, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
// The process just died? It's not the one we want then.
|
||||
continue
|
||||
}
|
||||
statFields := strings.SplitN(string(statBytes), " ", 5)
|
||||
if len(statFields) != 5 {
|
||||
return -1, fmt.Errorf("incomplete file %q", filename)
|
||||
}
|
||||
if statFields[3] == fmt.Sprintf("%d", ppid) {
|
||||
return int(pid64), nil
|
||||
}
|
||||
}
|
||||
|
||||
return -1, ErrChildNotReady{}
|
||||
}
|
||||
|
||||
// getPID returns the pid of the pod.
|
||||
func (p *pod) getPID() (pid int, err error) {
|
||||
// rkt supports two methods to find the container's PID 1:
|
||||
// the pid file and the ppid file.
|
||||
// See Documentation/devel/stage1-implementors-guide.md
|
||||
for {
|
||||
var ppid int
|
||||
|
||||
// No do { } while() Golang, seriously?
|
||||
for first := true; first || (os.IsNotExist(err) && p.isRunning()); first = false {
|
||||
pid, err = p.readIntFromFile("pid")
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
ppid, err = p.readIntFromFile("ppid")
|
||||
if err == nil {
|
||||
pid, err = getChildPID(ppid)
|
||||
if err == nil {
|
||||
return pid, nil
|
||||
}
|
||||
if _, ok := err.(ErrChildNotReady); ok {
|
||||
err = nil
|
||||
} else {
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
|
||||
// There's a window between a pod transitioning to run and the pid file being created by stage1.
|
||||
// The window shouldn't be large so we just delay and retry here. If stage1 fails to reach the
|
||||
// point of pid file creation, it will exit and p.isRunning() becomes false since we refreshState below.
|
||||
@@ -749,8 +833,11 @@ func (p *pod) getPID() (pid int, err error) {
|
||||
if err := p.refreshState(); err != nil {
|
||||
return -1, err
|
||||
}
|
||||
|
||||
if !os.IsNotExist(err) || !p.isRunning() {
|
||||
return -1, err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getStage1Hash returns the hash of the stage1 image used in this pod
|
||||
|
||||
@@ -52,5 +52,6 @@ for link in ${BUSYBOX_LINKS}; do
|
||||
done
|
||||
|
||||
echo "Busybox installed. Use the following command to enter pod's stage1:"
|
||||
SYSTEMD_PID=$(sudo cat "${RKT_RUN_DIR}/${UUID}/pid")
|
||||
SYSTEMD_PPID=$(sudo cat "${RKT_RUN_DIR}/${UUID}/ppid")
|
||||
SYSTEMD_PID=$(sudo cat /proc/$SYSTEMD_PPID/task/$SYSTEMD_PPID/children)
|
||||
echo sudo nsenter -m -u -i -p -t ${SYSTEMD_PID}
|
||||
|
||||
+15
-6
@@ -192,12 +192,6 @@ func getArgsEnv(p *Pod, flavor string, systemdStage1Version string, debug bool)
|
||||
// before execing init"), fds remain open, so --keep-fd is not needed.
|
||||
}
|
||||
|
||||
out, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
args = append(args, fmt.Sprintf("--pid-file=%v", filepath.Join(out, "pid")))
|
||||
|
||||
if machinedRegister() {
|
||||
args = append(args, fmt.Sprintf("--register=true"))
|
||||
} else {
|
||||
@@ -381,6 +375,21 @@ func stage1() int {
|
||||
return 3
|
||||
}
|
||||
|
||||
// write ppid file as specified in
|
||||
// Documentation/devel/stage1-implementors-guide.md
|
||||
out, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Cannot get current working directory: %v\n", err)
|
||||
return 4
|
||||
}
|
||||
// we are the parent of the process that is PID 1 in the container so we write our PID to "ppid"
|
||||
err = ioutil.WriteFile(filepath.Join(out, "ppid"),
|
||||
[]byte(fmt.Sprintf("%d\n", os.Getpid())), 0644)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Cannot write ppid file: %v\n", err)
|
||||
return 4
|
||||
}
|
||||
|
||||
var execFn func() error
|
||||
|
||||
if privNet.Any() {
|
||||
|
||||
@@ -28,16 +28,12 @@
|
||||
/* hack to make systemd-nspawn execute on non-sysd systems:
|
||||
* - intercept lstat() so lstat of /run/systemd/system always succeeds and returns a directory
|
||||
* - intercept close() to prevent nspawn closing the rkt lock, set it to CLOEXEC instead
|
||||
* - intercept syscall(SYS_clone) to record the pod's pid
|
||||
*/
|
||||
|
||||
#define ENV_LOCKFD "RKT_LOCK_FD"
|
||||
#define PIDFILE_TMP "pid.tmp"
|
||||
#define PIDFILE "pid"
|
||||
|
||||
static int (*libc_lxstat)(int, const char *, struct stat *);
|
||||
static int (*libc_close)(int);
|
||||
static long (*libc_syscall)(long number, ...);
|
||||
static int lock_fd = -1;
|
||||
|
||||
static __attribute__((constructor)) void wrapper_init(void)
|
||||
@@ -47,7 +43,6 @@ static __attribute__((constructor)) void wrapper_init(void)
|
||||
lock_fd = atoi(env);
|
||||
libc_lxstat = dlsym(RTLD_NEXT, "__lxstat");
|
||||
libc_close = dlsym(RTLD_NEXT, "close");
|
||||
libc_syscall = dlsym(RTLD_NEXT, "syscall");
|
||||
}
|
||||
|
||||
int __lxstat(int ver, const char *path, struct stat *stat)
|
||||
@@ -69,37 +64,3 @@ int close(int fd)
|
||||
|
||||
return libc_close(fd);
|
||||
}
|
||||
|
||||
long syscall(long number, ...)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
va_list ap;
|
||||
long ret;
|
||||
|
||||
/* XXX: we're targeting systemd-nspawn with this shim, its only syscall() use is __NR_clone */
|
||||
if(number != __NR_clone)
|
||||
return -1;
|
||||
|
||||
va_start(ap, number);
|
||||
clone_flags = va_arg(ap, unsigned long);
|
||||
va_end(ap);
|
||||
|
||||
ret = libc_syscall(number, clone_flags, NULL);
|
||||
|
||||
if(ret > 0) {
|
||||
int fd;
|
||||
/* in parent; try record the pod's pid */
|
||||
if((fd = open(PIDFILE_TMP, O_CREAT|O_WRONLY|O_SYNC, 0640)) != -1) {
|
||||
int len;
|
||||
char buf[20];
|
||||
|
||||
if((len = snprintf(buf, sizeof(buf), "%li\n", ret)) != -1)
|
||||
if(write(fd, buf, len) == len)
|
||||
rename(PIDFILE_TMP, PIDFILE);
|
||||
|
||||
libc_close(fd);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
From 54802a88288c44c098d0cbe884e698cdbd778de2 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Iago=20L=C3=B3pez=20Galeiras?= <iago@endocode.com>
|
||||
Date: Thu, 21 May 2015 16:52:48 +0200
|
||||
Subject: [PATCH] nspawn: add --pid-file
|
||||
|
||||
Simple mechanism for recording the container's pid independent of any
|
||||
external daemons/systemd services.
|
||||
|
||||
[patch ported to v219 -alban]
|
||||
[patch ported to git master 2015-05-20 -alban]
|
||||
[patch ported to git master 2015-05-21 -iaguis]
|
||||
---
|
||||
src/nspawn/nspawn.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index d6b24c6..be69172 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -190,6 +190,7 @@ static bool arg_quiet = false;
|
||||
static bool arg_share_system = false;
|
||||
static bool arg_register = true;
|
||||
static bool arg_keep_unit = false;
|
||||
+static const char *arg_pid_file = NULL;
|
||||
static char **arg_network_interfaces = NULL;
|
||||
static char **arg_network_macvlan = NULL;
|
||||
static char **arg_network_ipvlan = NULL;
|
||||
@@ -271,6 +272,7 @@ static void help(void) {
|
||||
" --keep-unit Do not register a scope for the machine, reuse\n"
|
||||
" the service unit nspawn is running in\n"
|
||||
" --volatile[=MODE] Run the system in volatile mode\n"
|
||||
+ " --pid-file=FILE Write child pid to FILE\n"
|
||||
, program_invocation_short_name);
|
||||
}
|
||||
|
||||
@@ -397,6 +399,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_SHARE_SYSTEM,
|
||||
ARG_REGISTER,
|
||||
ARG_KEEP_UNIT,
|
||||
+ ARG_PID_FILE,
|
||||
ARG_NETWORK_INTERFACE,
|
||||
ARG_NETWORK_MACVLAN,
|
||||
ARG_NETWORK_IPVLAN,
|
||||
@@ -437,6 +440,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "share-system", no_argument, NULL, ARG_SHARE_SYSTEM },
|
||||
{ "register", required_argument, NULL, ARG_REGISTER },
|
||||
{ "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
|
||||
+ { "pid-file", required_argument, NULL, ARG_PID_FILE },
|
||||
{ "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
|
||||
{ "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
|
||||
{ "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN },
|
||||
@@ -820,6 +824,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_keep_unit = true;
|
||||
break;
|
||||
|
||||
+ case ARG_PID_FILE:
|
||||
+ arg_pid_file = optarg;
|
||||
+ break;
|
||||
+
|
||||
case ARG_PERSONALITY:
|
||||
|
||||
arg_personality = personality_from_string(optarg);
|
||||
@@ -3920,6 +3928,14 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) {
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int write_pid(const char *f, int pid) {
|
||||
+ char pid_str[13]; /* -2147483646\n\0 */
|
||||
+
|
||||
+ snprintf(pid_str, sizeof(pid_str), "%i\n", pid);
|
||||
+ return write_string_file_atomic(f, pid_str);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static void nop_handler(int sig) {}
|
||||
|
||||
static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
@@ -4875,6 +4891,14 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
+ if (arg_pid_file) {
|
||||
+ r = write_pid(arg_pid_file, pid);
|
||||
+ if (r < 0) {
|
||||
+ log_error_errno(r, "Failed to write pid file: %m");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
sd_notifyf(false,
|
||||
"READY=1\n"
|
||||
"STATUS=Container running.\n"
|
||||
--
|
||||
2.4.1
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
From b7c75246350bd7af55f80dd9ac89c23682765aaf Mon Sep 17 00:00:00 2001
|
||||
From: Vito Caputo <vito.caputo@coreos.com>
|
||||
Date: Mon, 16 Mar 2015 15:13:49 -0700
|
||||
Subject: [PATCH 3/3] nspawn: add --pid-file
|
||||
|
||||
Simple mechanism for recording the container's pid independent of any external
|
||||
daemons/systemd services.
|
||||
---
|
||||
src/nspawn/nspawn.c | 23 ++++++++++++++++++++++-
|
||||
1 file changed, 22 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index 0277a12..6650629 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -154,6 +154,7 @@ static bool arg_share_system = false;
|
||||
static bool arg_register = true;
|
||||
static bool arg_keep_unit = false;
|
||||
static int arg_keep_fd = -1;
|
||||
+static const char *arg_pid_file = NULL;
|
||||
static char **arg_network_interfaces = NULL;
|
||||
static char **arg_network_macvlan = NULL;
|
||||
static bool arg_network_veth = false;
|
||||
@@ -209,7 +210,8 @@ static int help(void) {
|
||||
" --register=BOOLEAN Register container as machine\n"
|
||||
" --keep-unit Do not register a scope for the machine, reuse\n"
|
||||
" the service unit nspawn is running in\n"
|
||||
- " --keep-fd=FDNUM Do not close the specified file descriptor\n",
|
||||
+ " --keep-fd=FDNUM Do not close the specified file descriptor\n"
|
||||
+ " --pid-file=FILE Write child pid to FILE\n",
|
||||
program_invocation_short_name);
|
||||
|
||||
return 0;
|
||||
@@ -233,6 +235,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_REGISTER,
|
||||
ARG_KEEP_UNIT,
|
||||
ARG_KEEP_FD,
|
||||
+ ARG_PID_FILE,
|
||||
ARG_NETWORK_INTERFACE,
|
||||
ARG_NETWORK_MACVLAN,
|
||||
ARG_NETWORK_VETH,
|
||||
@@ -265,6 +268,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "register", required_argument, NULL, ARG_REGISTER },
|
||||
{ "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
|
||||
{ "keep-fd", required_argument, NULL, ARG_KEEP_FD },
|
||||
+ { "pid-file", required_argument, NULL, ARG_PID_FILE },
|
||||
{ "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
|
||||
{ "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
|
||||
{ "network-veth", no_argument, NULL, ARG_NETWORK_VETH },
|
||||
@@ -561,6 +565,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
+ case ARG_PID_FILE:
|
||||
+ arg_pid_file = optarg;
|
||||
+ break;
|
||||
+
|
||||
case ARG_PERSONALITY:
|
||||
|
||||
arg_personality = personality_from_string(optarg);
|
||||
@@ -2757,6 +2765,13 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) {
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int write_pid(const char *f, int pid) {
|
||||
+ char pid_str[13]; /* -2147483646\n\0 */
|
||||
+
|
||||
+ snprintf(pid_str, sizeof(pid_str), "%i\n", pid);
|
||||
+ return write_string_file_atomic(f, pid_str);
|
||||
+}
|
||||
+
|
||||
static void nop_handler(int sig) {}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
@@ -3317,6 +3332,12 @@ int main(int argc, char *argv[]) {
|
||||
eventfds[1] = safe_close(eventfds[1]);
|
||||
|
||||
if (r >= 0) {
|
||||
+ if (arg_pid_file) {
|
||||
+ r = write_pid(arg_pid_file, pid);
|
||||
+ if (r < 0)
|
||||
+ goto finish;
|
||||
+ }
|
||||
+
|
||||
r = register_machine(pid);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
From 30b585a02cfad4c0f420f70146bb6bc4566def85 Mon Sep 17 00:00:00 2001
|
||||
From: Vito Caputo <vito.caputo@coreos.com>
|
||||
Date: Mon, 16 Mar 2015 15:13:49 -0700
|
||||
Subject: [PATCH 2/4] nspawn: add --pid-file
|
||||
|
||||
Simple mechanism for recording the container's pid independent of any external
|
||||
daemons/systemd services.
|
||||
|
||||
[patch ported to v219 -alban]
|
||||
---
|
||||
src/nspawn/nspawn.c | 23 +++++++++++++++++++++++
|
||||
1 file changed, 23 insertions(+)
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index b7c9da5..5ea07c4 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -179,6 +179,7 @@ static bool arg_share_system = false;
|
||||
static bool arg_register = true;
|
||||
static bool arg_keep_unit = false;
|
||||
static int arg_keep_fd = -1;
|
||||
+static const char *arg_pid_file = NULL;
|
||||
static char **arg_network_interfaces = NULL;
|
||||
static char **arg_network_macvlan = NULL;
|
||||
static char **arg_network_ipvlan = NULL;
|
||||
@@ -248,6 +249,7 @@ static void help(void) {
|
||||
" the service unit nspawn is running in\n"
|
||||
" --volatile[=MODE] Run the system in volatile mode\n"
|
||||
" --keep-fd=FDNUM Do not close the specified file descriptor\n"
|
||||
+ " --pid-file=FILE Write child pid to FILE\n"
|
||||
, program_invocation_short_name);
|
||||
}
|
||||
|
||||
@@ -290,6 +292,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_REGISTER,
|
||||
ARG_KEEP_UNIT,
|
||||
ARG_KEEP_FD,
|
||||
+ ARG_PID_FILE,
|
||||
ARG_NETWORK_INTERFACE,
|
||||
ARG_NETWORK_MACVLAN,
|
||||
ARG_NETWORK_IPVLAN,
|
||||
@@ -326,6 +329,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "register", required_argument, NULL, ARG_REGISTER },
|
||||
{ "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
|
||||
{ "keep-fd", required_argument, NULL, ARG_KEEP_FD },
|
||||
+ { "pid-file", required_argument, NULL, ARG_PID_FILE },
|
||||
{ "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
|
||||
{ "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
|
||||
{ "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN },
|
||||
@@ -655,6 +659,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
}
|
||||
break;
|
||||
|
||||
+ case ARG_PID_FILE:
|
||||
+ arg_pid_file = optarg;
|
||||
+ break;
|
||||
+
|
||||
case ARG_PERSONALITY:
|
||||
|
||||
arg_personality = personality_from_string(optarg);
|
||||
@@ -3495,6 +3503,13 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) {
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int write_pid(const char *f, int pid) {
|
||||
+ char pid_str[13]; /* -2147483646\n\0 */
|
||||
+
|
||||
+ snprintf(pid_str, sizeof(pid_str), "%i\n", pid);
|
||||
+ return write_string_file_atomic(f, pid_str);
|
||||
+}
|
||||
+
|
||||
static void nop_handler(int sig) {}
|
||||
|
||||
static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
@@ -4237,6 +4252,14 @@ int main(int argc, char *argv[]) {
|
||||
_cleanup_rtnl_unref_ sd_rtnl *rtnl = NULL;
|
||||
char last_char = 0;
|
||||
|
||||
+ if (arg_pid_file) {
|
||||
+ r = write_pid(arg_pid_file, pid);
|
||||
+ if (r < 0) {
|
||||
+ log_error_errno(r, "Failed to write pid file: %m");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
sd_notifyf(false,
|
||||
"READY=1\n"
|
||||
"STATUS=Container running.\n"
|
||||
--
|
||||
2.1.4
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
From a7bfa4b16a833ff5e2b25e28b406c300a8d3e318 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Iago=20L=C3=B3pez=20Galeiras?= <iago@endocode.com>
|
||||
Date: Thu, 21 May 2015 16:52:48 +0200
|
||||
Subject: [PATCH] nspawn: add --pid-file
|
||||
|
||||
Simple mechanism for recording the container's pid independent of any
|
||||
external daemons/systemd services.
|
||||
|
||||
[patch ported to v219 -alban]
|
||||
[patch ported to git master 2015-05-20 -alban]
|
||||
[patch ported to git master 2015-05-21 -iaguis]
|
||||
[patch ported to v220 2015-05-26 -alban]
|
||||
---
|
||||
src/nspawn/nspawn.c | 24 ++++++++++++++++++++++++
|
||||
1 file changed, 24 insertions(+)
|
||||
|
||||
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
|
||||
index 5009363..41c034c 100644
|
||||
--- a/src/nspawn/nspawn.c
|
||||
+++ b/src/nspawn/nspawn.c
|
||||
@@ -190,6 +190,7 @@ static bool arg_quiet = false;
|
||||
static bool arg_share_system = false;
|
||||
static bool arg_register = true;
|
||||
static bool arg_keep_unit = false;
|
||||
+static const char *arg_pid_file = NULL;
|
||||
static char **arg_network_interfaces = NULL;
|
||||
static char **arg_network_macvlan = NULL;
|
||||
static char **arg_network_ipvlan = NULL;
|
||||
@@ -271,6 +272,7 @@ static void help(void) {
|
||||
" --keep-unit Do not register a scope for the machine, reuse\n"
|
||||
" the service unit nspawn is running in\n"
|
||||
" --volatile[=MODE] Run the system in volatile mode\n"
|
||||
+ " --pid-file=FILE Write child pid to FILE\n"
|
||||
, program_invocation_short_name);
|
||||
}
|
||||
|
||||
@@ -397,6 +399,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_SHARE_SYSTEM,
|
||||
ARG_REGISTER,
|
||||
ARG_KEEP_UNIT,
|
||||
+ ARG_PID_FILE,
|
||||
ARG_NETWORK_INTERFACE,
|
||||
ARG_NETWORK_MACVLAN,
|
||||
ARG_NETWORK_IPVLAN,
|
||||
@@ -437,6 +440,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "share-system", no_argument, NULL, ARG_SHARE_SYSTEM },
|
||||
{ "register", required_argument, NULL, ARG_REGISTER },
|
||||
{ "keep-unit", no_argument, NULL, ARG_KEEP_UNIT },
|
||||
+ { "pid-file", required_argument, NULL, ARG_PID_FILE },
|
||||
{ "network-interface", required_argument, NULL, ARG_NETWORK_INTERFACE },
|
||||
{ "network-macvlan", required_argument, NULL, ARG_NETWORK_MACVLAN },
|
||||
{ "network-ipvlan", required_argument, NULL, ARG_NETWORK_IPVLAN },
|
||||
@@ -820,6 +824,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_keep_unit = true;
|
||||
break;
|
||||
|
||||
+ case ARG_PID_FILE:
|
||||
+ arg_pid_file = optarg;
|
||||
+ break;
|
||||
+
|
||||
case ARG_PERSONALITY:
|
||||
|
||||
arg_personality = personality_from_string(optarg);
|
||||
@@ -3921,6 +3929,14 @@ static int wait_for_container(pid_t pid, ContainerStatus *container) {
|
||||
return r;
|
||||
}
|
||||
|
||||
+static int write_pid(const char *f, int pid) {
|
||||
+ char pid_str[13]; /* -2147483646\n\0 */
|
||||
+
|
||||
+ snprintf(pid_str, sizeof(pid_str), "%i\n", pid);
|
||||
+ return write_string_file_atomic(f, pid_str);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static void nop_handler(int sig) {}
|
||||
|
||||
static int on_orderly_shutdown(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
|
||||
@@ -4876,6 +4892,14 @@ int main(int argc, char *argv[]) {
|
||||
goto finish;
|
||||
}
|
||||
|
||||
+ if (arg_pid_file) {
|
||||
+ r = write_pid(arg_pid_file, pid);
|
||||
+ if (r < 0) {
|
||||
+ log_error_errno(r, "Failed to write pid file: %m");
|
||||
+ goto finish;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
sd_notifyf(false,
|
||||
"READY=1\n"
|
||||
"STATUS=Container running.\n"
|
||||
--
|
||||
2.1.4
|
||||
|
||||
Reference in New Issue
Block a user