Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Lib/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -2302,6 +2302,8 @@ def _wait_kqueue(self, timeout):
_MAXIMUM_WAIT_TIMEOUT)
try:
events = kq.control(changelist, 1, max(delay, 0))
except InterruptedError:
raise
except OSError:
return False
if events:
Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -4311,6 +4311,21 @@ def test_kqueue_control_error(self):
self.assertEqual(p.wait(timeout=support.SHORT_TIMEOUT), 0)
self.assertTrue(m.called)

@unittest.skipIf(not CAN_USE_KQUEUE, reason="needs kqueue() for proc")
def test_kqueue_control_interrupted_error(self):
p = subprocess.Popen(self.COMMAND)
kq_mock = mock.Mock()
kq_mock.control.side_effect = InterruptedError
kq_mock.close = mock.Mock()
try:
with mock.patch("select.kqueue", return_value=kq_mock):
with self.assertRaises(InterruptedError):
p.wait(self.WAIT_TIMEOUT)
finally:
p.kill()
p.wait()
self.assertTrue(kq_mock.control.called)

def assert_wait_race_condition(self, patch_target, real_func):
# Call pidfd_open() / kqueue(), then terminate the process.
# Make sure that the wait call (poll() / kqueue.control())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Propagate :exc:`InterruptedError` from :meth:`subprocess.Popen.wait` when
waiting with ``kqueue`` instead of swallowing it as an ordinary operating
system error.
Loading