Browse code

Merge pull request #5792 from bernerdschaefer/nsinit-supports-pdeathsig

Add PDEATHSIG support to nsinit library

Victor Marmol authored on 2014/05/20 03:13:23
Showing 3 changed files
... ...
@@ -123,6 +123,7 @@ func DefaultCreateCommand(container *libcontainer.Container, console, rootfs, da
123 123
 	command.Env = append(os.Environ(), env...)
124 124
 
125 125
 	system.SetCloneFlags(command, uintptr(GetNamespaceFlags(container.Namespaces)))
126
+	command.SysProcAttr.Pdeathsig = syscall.SIGKILL
126 127
 	command.ExtraFiles = []*os.File{pipe}
127 128
 
128 129
 	return command
... ...
@@ -85,12 +85,53 @@ func Init(container *libcontainer.Container, uncleanRootfs, consolePath string,
85 85
 			return err
86 86
 		}
87 87
 	}
88
+
89
+	pdeathSignal, err := system.GetParentDeathSignal()
90
+	if err != nil {
91
+		return fmt.Errorf("get parent death signal %s", err)
92
+	}
93
+
88 94
 	if err := FinalizeNamespace(container); err != nil {
89 95
 		return fmt.Errorf("finalize namespace %s", err)
90 96
 	}
97
+
98
+	// FinalizeNamespace can change user/group which clears the parent death
99
+	// signal, so we restore it here.
100
+	if err := RestoreParentDeathSignal(pdeathSignal); err != nil {
101
+		return fmt.Errorf("restore parent death signal %s", err)
102
+	}
103
+
91 104
 	return system.Execv(args[0], args[0:], container.Env)
92 105
 }
93 106
 
107
+// RestoreParentDeathSignal sets the parent death signal to old.
108
+func RestoreParentDeathSignal(old int) error {
109
+	if old == 0 {
110
+		return nil
111
+	}
112
+
113
+	current, err := system.GetParentDeathSignal()
114
+	if err != nil {
115
+		return fmt.Errorf("get parent death signal %s", err)
116
+	}
117
+
118
+	if old == current {
119
+		return nil
120
+	}
121
+
122
+	if err := system.ParentDeathSignal(uintptr(old)); err != nil {
123
+		return fmt.Errorf("set parent death signal %s", err)
124
+	}
125
+
126
+	// Signal self if parent is already dead. Does nothing if running in a new
127
+	// PID namespace, as Getppid will always return 0.
128
+	if syscall.Getppid() == 1 {
129
+		return syscall.Kill(syscall.Getpid(), syscall.Signal(old))
130
+	}
131
+
132
+	return nil
133
+}
134
+
94 135
 // SetupUser changes the groups, gid, and uid for the user inside the container
95 136
 func SetupUser(u string) error {
96 137
 	uid, gid, suppGids, err := user.GetUserGroupSupplementary(u, syscall.Getuid(), syscall.Getgid())
... ...
@@ -3,6 +3,7 @@ package system
3 3
 import (
4 4
 	"os/exec"
5 5
 	"syscall"
6
+	"unsafe"
6 7
 )
7 8
 
8 9
 func Chroot(dir string) error {
... ...
@@ -122,6 +123,18 @@ func ParentDeathSignal(sig uintptr) error {
122 122
 	return nil
123 123
 }
124 124
 
125
+func GetParentDeathSignal() (int, error) {
126
+	var sig int
127
+
128
+	_, _, err := syscall.RawSyscall(syscall.SYS_PRCTL, syscall.PR_GET_PDEATHSIG, uintptr(unsafe.Pointer(&sig)), 0)
129
+
130
+	if err != 0 {
131
+		return -1, err
132
+	}
133
+
134
+	return sig, nil
135
+}
136
+
125 137
 func Setctty() error {
126 138
 	if _, _, err := syscall.RawSyscall(syscall.SYS_IOCTL, 0, uintptr(syscall.TIOCSCTTY), 0); err != 0 {
127 139
 		return err