File: kill.bats

package info (click to toggle)
runc 1.3.3%2Bds1-3
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 3,136 kB
  • sloc: sh: 2,298; ansic: 1,125; makefile: 229
file content (159 lines) | stat: -rw-r--r-- 4,843 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#!/usr/bin/env bats

load helpers

function setup() {
	setup_busybox
}

function teardown() {
	teardown_bundle
}

# This needs to be placed at the top of the bats file to work around
# a shellcheck bug. See <https://github.com/koalaman/shellcheck/issues/2873>.
test_host_pidns_kill() {
	requires cgroups_freezer

	update_config '	  .linux.namespaces -= [{"type": "pid"}]'
	set_cgroups_path
	if [ $EUID -ne 0 ]; then
		requires rootless_cgroup
		# Can't mount real /proc when rootless + no pidns,
		# so change it to a bind-mounted one from the host.
		update_config '	  .mounts |= map((select(.type == "proc")
					| .type = "none"
					| .source = "/proc"
					| .options = ["rbind", "nosuid", "nodev", "noexec"]
				  ) // .)'
	fi

	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
	[ "$status" -eq 0 ]
	cgpath=$(get_cgroup_path "pids")
	init_pid=$(cat "$cgpath"/cgroup.procs)

	# Start a few more processes.
	for _ in 1 2 3 4 5; do
		__runc exec -d test_busybox sleep 1h
	done

	if [ -v KILL_INIT ]; then
		# Now kill the container's init process. Since the container do
		# not have own PID ns, its init is no special and the container
		# will still be up and running (except for rootless container
		# AND systemd cgroup driver AND systemd > v245, when systemd
		# kills the container; see "kill KILL [host pidns + init gone]"
		# below).
		kill -9 "$init_pid"
		wait_pids_gone 10 0.2 "$init_pid"
	fi

	# Get the list of all container processes.
	mapfile -t pids < <(cat "$cgpath"/cgroup.procs)
	echo "pids:" "${pids[@]}"
	# Sanity check -- make sure all processes exist.
	for p in "${pids[@]}"; do
		kill -0 "$p"
	done

	runc kill test_busybox KILL
	[ "$status" -eq 0 ]
	# Wait and check that all processes are gone.
	wait_pids_gone 10 0.2 "${pids[@]}"

	# Make sure the container is in stopped state. Note if KILL_INIT
	# is set, container was already stopped by killing its $init_pid
	# and so this check is NOP/redundant.
	testcontainer test_busybox stopped

	# Make sure cgroup.procs is empty.
	mapfile -t pids < <(cat "$cgpath"/cgroup.procs || true)
	if [ ${#pids[@]} -gt 0 ]; then
		echo "expected empty cgroup.procs, got:" "${pids[@]}" 1>&2
		return 1
	fi
}

@test "kill detached busybox" {
	# run busybox detached
	runc run -d --console-socket "$CONSOLE_SOCKET" test_busybox
	[ "$status" -eq 0 ]

	# check state
	testcontainer test_busybox running

	runc kill test_busybox KILL
	[ "$status" -eq 0 ]
	wait_for_container 10 1 test_busybox stopped

	# Check that kill errors on a stopped container.
	runc kill test_busybox 0
	[ "$status" -ne 0 ]
	[[ "$output" == *"container not running"* ]]

	# Check that -a (now obsoleted) makes kill return no error for a stopped container.
	runc kill -a test_busybox 0
	[ "$status" -eq 0 ]

	runc delete test_busybox
	[ "$status" -eq 0 ]
}

# This is roughly the same as TestPIDHostInitProcessWait in libcontainer/integration.
# The differences are:
#
# 1. Here we use separate processes to create and to kill a container, so the
#    processes inside a container are not children of "runc kill".
#
# 2. We hit different codepaths (nonChildProcess.signal rather than initProcess.signal).
@test "kill KILL [host pidns]" {
	unset KILL_INIT
	test_host_pidns_kill
}

# Same as above plus:
#
# 3. Test runc kill on a container whose init process is gone.
#
# Issue 4047, case "runc kill".
# See also: "runc delete --force [host pidns + init gone]" test in delete.bats.
@test "kill KILL [host pidns + init gone]" {
	# Apparently, for rootless test, when using systemd cgroup manager,
	# newer versions of systemd clean up the container as soon as its init
	# process is gone. This is all fine and dandy, except it prevents us to
	# test this case, thus we skip the test.
	#
	# It is not entirely clear which systemd version got this feature:
	# v245 works fine, and v249 does not.
	if [ $EUID -ne 0 ] && [ -v RUNC_USE_SYSTEMD ] && [ "$(systemd_version)" -gt 245 ]; then
		skip "rootless+systemd conflicts with systemd > 245"
	fi
	KILL_INIT=1
	test_host_pidns_kill
	unset KILL_INIT
}

# https://github.com/opencontainers/runc/issues/4394 (cgroup v1, rootless)
@test "kill KILL [shared pidns]" {
	update_config '.process.args = ["sleep", "infinity"]'

	runc run -d --console-socket "$CONSOLE_SOCKET" target_ctr
	[ "$status" -eq 0 ]
	testcontainer target_ctr running
	target_pid="$(__runc state target_ctr | jq .pid)"
	update_config '.linux.namespaces |= map(if .type == "user" or .type == "pid" then (.path = "/proc/'"$target_pid"'/ns/" + .type) else . end) | del(.linux.uidMappings) | del(.linux.gidMappings)'

	runc run -d --console-socket "$CONSOLE_SOCKET" attached_ctr
	[ "$status" -eq 0 ]
	testcontainer attached_ctr running

	runc kill attached_ctr 9
	[ "$status" -eq 0 ]

	runc delete --force attached_ctr
	[ "$status" -eq 0 ]

	runc delete --force target_ctr
	[ "$status" -eq 0 ]
}