- Notifications
You must be signed in to change notification settings - Fork 1.9k
/
Copy pathtest_signals.py
133 lines (106 loc) · 4.05 KB
/
test_signals.py
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
# Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Tests scenarios for Firecracker signal handling."""
importjson
importos
importresourceasres
fromsignalimportSIGBUS, SIGHUP, SIGILL, SIGPIPE, SIGSEGV, SIGSYS, SIGXCPU, SIGXFSZ
fromtimeimportsleep
importpytest
signum_str= {
SIGBUS: "sigbus",
SIGSEGV: "sigsegv",
SIGXFSZ: "sigxfsz",
SIGXCPU: "sigxcpu",
SIGPIPE: "sigpipe",
SIGHUP: "sighup",
SIGILL: "sigill",
SIGSYS: "sigsys",
}
@pytest.mark.parametrize(
"signum", [SIGBUS, SIGSEGV, SIGXFSZ, SIGXCPU, SIGPIPE, SIGHUP, SIGILL, SIGSYS]
)
deftest_generic_signal_handler(uvm_plain, signum):
"""
Test signal handling for all handled signals.
"""
microvm=uvm_plain
microvm.spawn()
# We don't need to monitor the memory for this test.
microvm.memory_monitor=None
microvm.basic_config()
microvm.start()
sleep(0.5)
metrics_jail_path=microvm.metrics_file
metrics_fd=open(metrics_jail_path, encoding="utf-8")
line_metrics=metrics_fd.readlines()
assertlen(line_metrics) ==1
os.kill(microvm.firecracker_pid, signum)
# Firecracker gracefully handles SIGPIPE (doesn't terminate).
ifsignum==int(SIGPIPE):
msg="Received signal 13"
# Flush metrics to file, so we can see the SIGPIPE at bottom assert.
# This is going to fail if process has exited.
microvm.api.actions.put(action_type="FlushMetrics")
else:
msg="Shutting down VM after intercepting signal {}".format(signum)
microvm.mark_killed()
microvm.check_log_message(msg)
ifsignum!=SIGSYS:
metric_line=json.loads(metrics_fd.readlines()[0])
assertmetric_line["signals"][signum_str[signum]] ==1
deftest_sigxfsz_handler(uvm_plain_rw):
"""
Test intercepting and handling SIGXFSZ.
"""
microvm=uvm_plain_rw
microvm.spawn()
# We don't need to monitor the memory for this test.
microvm.memory_monitor=None
# We need to use the Sync file engine type. If we use io_uring we will not
# get a SIGXFSZ. We'll instead get an errno 27 File too large as the
# completed entry status code.
microvm.basic_config(rootfs_io_engine="Sync")
microvm.start()
metrics_jail_path=microvm.metrics_file
metrics_fd=open(metrics_jail_path, encoding="utf-8")
line_metrics=metrics_fd.readlines()
assertlen(line_metrics) ==1
firecracker_pid=microvm.firecracker_pid
size=os.path.getsize(metrics_jail_path)
# The SIGXFSZ is triggered because the size of rootfs is bigger than
# the size of metrics file times 3. Since the metrics file is flushed
# twice we have to make sure that the limit is bigger than that
# in order to make sure the SIGXFSZ metric is logged
res.prlimit(firecracker_pid, res.RLIMIT_FSIZE, (size*3, res.RLIM_INFINITY))
microvm.mark_killed()
msg="Shutting down VM after intercepting signal 25, code 0"
microvm.check_log_message(msg)
metric_line=json.loads(metrics_fd.readlines()[0])
assertmetric_line["signals"]["sigxfsz"] ==1
deftest_handled_signals(uvm_plain):
"""
Test that handled signals don't kill the microVM.
"""
microvm=uvm_plain
microvm.spawn()
# We don't need to monitor the memory for this test.
microvm.memory_monitor=None
microvm.basic_config(vcpu_count=2)
microvm.add_net_iface()
microvm.start()
# Open a SSH connection to validate the microVM stays alive.
# Just validate a simple command: `nproc`
cmd="nproc"
_, stdout, stderr=microvm.ssh.run(cmd)
assertstderr==""
assertint(stdout) ==2
# We have a handler installed for this signal.
# The 35 is the SIGRTMIN for musl libc.
# We hardcode this value since the SIGRTMIN python reports
# is 34, which is likely the one for glibc.
os.kill(microvm.firecracker_pid, 35)
# Validate the microVM is still up and running.
_, stdout, stderr=microvm.ssh.run(cmd)
assertstderr==""
assertint(stdout) ==2