Skip to content

Commit 8300809

Browse files
authored
bpo-31034: Reliable signal handler for test_asyncio (#2867)
* bpo-31034: Reliable signal handler for test_asyncio Don't rely on the current SIGHUP signal handler, make sure that it's set to the "default" signal handler: SIG_DFL. * Add comments
1 parent 302bbbe commit 8300809

File tree

2 files changed

+45
-31
lines changed

2 files changed

+45
-31
lines changed

Lib/test/test_asyncio/test_events.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1980,19 +1980,26 @@ def test_subprocess_terminate(self):
19801980

19811981
@unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP")
19821982
def test_subprocess_send_signal(self):
1983-
prog = os.path.join(os.path.dirname(__file__), 'echo.py')
1984-
1985-
connect = self.loop.subprocess_exec(
1986-
functools.partial(MySubprocessProtocol, self.loop),
1987-
sys.executable, prog)
1988-
transp, proto = self.loop.run_until_complete(connect)
1989-
self.assertIsInstance(proto, MySubprocessProtocol)
1990-
self.loop.run_until_complete(proto.connected)
1991-
1992-
transp.send_signal(signal.SIGHUP)
1993-
self.loop.run_until_complete(proto.completed)
1994-
self.assertEqual(-signal.SIGHUP, proto.returncode)
1995-
transp.close()
1983+
# bpo-31034: Make sure that we get the default signal handler (killing
1984+
# the process). The parent process may have decided to ignore SIGHUP,
1985+
# and signal handlers are inherited.
1986+
old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL)
1987+
try:
1988+
prog = os.path.join(os.path.dirname(__file__), 'echo.py')
1989+
1990+
connect = self.loop.subprocess_exec(
1991+
functools.partial(MySubprocessProtocol, self.loop),
1992+
sys.executable, prog)
1993+
transp, proto = self.loop.run_until_complete(connect)
1994+
self.assertIsInstance(proto, MySubprocessProtocol)
1995+
self.loop.run_until_complete(proto.connected)
1996+
1997+
transp.send_signal(signal.SIGHUP)
1998+
self.loop.run_until_complete(proto.completed)
1999+
self.assertEqual(-signal.SIGHUP, proto.returncode)
2000+
transp.close()
2001+
finally:
2002+
signal.signal(signal.SIGHUP, old_handler)
19962003

19972004
def test_subprocess_stderr(self):
19982005
prog = os.path.join(os.path.dirname(__file__), 'echo2.py')

Lib/test/test_asyncio/test_subprocess.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -166,25 +166,32 @@ def test_terminate(self):
166166

167167
@unittest.skipIf(sys.platform == 'win32', "Don't have SIGHUP")
168168
def test_send_signal(self):
169-
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
170-
args = [sys.executable, '-c', code]
171-
create = asyncio.create_subprocess_exec(*args,
172-
stdout=subprocess.PIPE,
173-
loop=self.loop)
174-
proc = self.loop.run_until_complete(create)
175-
176-
@asyncio.coroutine
177-
def send_signal(proc):
178-
# basic synchronization to wait until the program is sleeping
179-
line = yield from proc.stdout.readline()
180-
self.assertEqual(line, b'sleeping\n')
169+
# bpo-31034: Make sure that we get the default signal handler (killing
170+
# the process). The parent process may have decided to ignore SIGHUP,
171+
# and signal handlers are inherited.
172+
old_handler = signal.signal(signal.SIGHUP, signal.SIG_DFL)
173+
try:
174+
code = 'import time; print("sleeping", flush=True); time.sleep(3600)'
175+
args = [sys.executable, '-c', code]
176+
create = asyncio.create_subprocess_exec(*args,
177+
stdout=subprocess.PIPE,
178+
loop=self.loop)
179+
proc = self.loop.run_until_complete(create)
181180

182-
proc.send_signal(signal.SIGHUP)
183-
returncode = (yield from proc.wait())
184-
return returncode
185-
186-
returncode = self.loop.run_until_complete(send_signal(proc))
187-
self.assertEqual(-signal.SIGHUP, returncode)
181+
@asyncio.coroutine
182+
def send_signal(proc):
183+
# basic synchronization to wait until the program is sleeping
184+
line = yield from proc.stdout.readline()
185+
self.assertEqual(line, b'sleeping\n')
186+
187+
proc.send_signal(signal.SIGHUP)
188+
returncode = (yield from proc.wait())
189+
return returncode
190+
191+
returncode = self.loop.run_until_complete(send_signal(proc))
192+
self.assertEqual(-signal.SIGHUP, returncode)
193+
finally:
194+
signal.signal(signal.SIGHUP, old_handler)
188195

189196
def prepare_broken_pipe_test(self):
190197
# buffer large enough to feed the whole pipe buffer

0 commit comments

Comments
 (0)