43
43
super(TestBreakin, self).setUp()
44
if breakin.determine_signal() is None:
45
raise tests.TestSkipped('this platform is missing SIGQUIT'
44
self.requireFeature(tests.BreakinFeature)
47
45
if sys.platform == 'win32':
48
# Windows doesn't have os.kill, and we catch the SIGBREAK signal.
49
# We trigger SIGBREAK via a Console api so we need ctypes to access
52
raise tests.UnavailableFeature('ctypes')
53
46
self._send_signal = self._send_signal_win32
55
48
self._send_signal = self._send_signal_via_kill
61
54
sig_num = signal.SIGKILL
63
56
raise ValueError("unknown signal type: %s" % (sig_type,))
60
if e.errno != errno.ESRCH:
66
63
def _send_signal_win32(self, pid, sig_type):
67
64
"""Send a 'signal' on Windows.
110
107
raise tests.TestNotApplicable(
111
108
'%s raises a popup on OSX' % self.id())
113
def _wait_for_process(self, pid, sig=None):
110
def _wait_for_process(self, pid, sig=None, count=100):
114
111
# We don't know quite how long waiting for the process 'pid' will take,
115
112
# but if it's more than 10s then it's probably not going to work.
113
for i in range(count):
118
114
if sig is not None:
119
115
self._send_signal(pid, sig)
120
116
# Use WNOHANG to ensure we don't get blocked, doing so, we may
127
123
# instead. Most notably, the WNOHANG isn't allowed, so
128
124
# this can hang indefinitely.
129
125
pid_killed, returncode = os.waitpid(pid, opts)
130
if (pid_killed, returncode) != (0, 0):
126
if pid_killed != 0 and returncode != 0:
131
127
if sig is not None:
132
128
# high bit in low byte says if core was dumped; we
161
159
# os.read(proc.stderr.fileno())?
162
160
err = proc.stderr.readline()
163
161
self.assertContainsRe(err, r'entering debugger')
162
# Try to shutdown cleanly;
164
163
# Now that the debugger is entered, we can ask him to quit
165
164
proc.stdin.write("q\n")
166
# We wait a bit to let the child process handles our query and avoid
167
# triggering deadlocks leading to hangs on multi-core hosts...
168
dead, sig = self._wait_for_process(proc.pid)
165
# But we don't really care if it doesn't.
166
dead, sig = self._wait_for_process(proc.pid, count=3)
170
# The process didn't finish, let's kill it before reporting failure
171
dead, sig = self._wait_for_process(proc.pid, 'kill')
173
raise tests.KnownFailure(
174
"subprocess wasn't terminated, it had to be killed")
176
self.fail("subprocess %d wasn't terminated by repeated SIGKILL",
168
# The process didn't finish, let's kill it.
169
dead, sig = self._wait_for_process(proc.pid, 'kill', count=10)
171
# process isn't gone, user will have to hunt it down and kill
173
self.fail("subprocess %d wasn't terminated by repeated SIGKILL" %
179
176
def test_breakin_harder(self):