MCPcopy Index your code
hub / github.com/python/cpython / test_threadsafe_wait

Method test_threadsafe_wait

Lib/test/test_subprocess.py:1565–1615  ·  view source on GitHub ↗

Issue21291: Popen.wait() needs to be threadsafe for returncode.

(self)

Source from the content-addressed store, hash-verified

1563 raise exc
1564
1565 def test_threadsafe_wait(self):
1566 """Issue21291: Popen.wait() needs to be threadsafe for returncode."""
1567 proc = subprocess.Popen([sys.executable, '-c',
1568 'import time; time.sleep(12)'])
1569 self.assertEqual(proc.returncode, None)
1570 results = []
1571
1572 def kill_proc_timer_thread():
1573 results.append(('thread-start-poll-result', proc.poll()))
1574 # terminate it from the thread and wait for the result.
1575 proc.kill()
1576 proc.wait()
1577 results.append(('thread-after-kill-and-wait', proc.returncode))
1578 # this wait should be a no-op given the above.
1579 proc.wait()
1580 results.append(('thread-after-second-wait', proc.returncode))
1581
1582 # This is a timing sensitive test, the failure mode is
1583 # triggered when both the main thread and this thread are in
1584 # the wait() call at once. The delay here is to allow the
1585 # main thread to most likely be blocked in its wait() call.
1586 t = threading.Timer(0.2, kill_proc_timer_thread)
1587 t.start()
1588
1589 if mswindows:
1590 expected_errorcode = 1
1591 else:
1592 # Should be -9 because of the proc.kill() from the thread.
1593 expected_errorcode = -9
1594
1595 # Wait for the process to finish; the thread should kill it
1596 # long before it finishes on its own. Supplying a timeout
1597 # triggers a different code path for better coverage.
1598 proc.wait(timeout=support.SHORT_TIMEOUT)
1599 self.assertEqual(proc.returncode, expected_errorcode,
1600 msg="unexpected result in wait from main thread")
1601
1602 # This should be a no-op with no change in returncode.
1603 proc.wait()
1604 self.assertEqual(proc.returncode, expected_errorcode,
1605 msg="unexpected result in second main wait.")
1606
1607 t.join()
1608 # Ensure that all of the thread results are as expected.
1609 # When a race condition occurs in wait(), the returncode could
1610 # be set by the wrong thread that doesn't actually have it
1611 # leading to an incorrect value.
1612 self.assertEqual([('thread-start-poll-result', None),
1613 ('thread-after-kill-and-wait', expected_errorcode),
1614 ('thread-after-second-wait', expected_errorcode)],
1615 results)
1616
1617 def test_issue8780(self):
1618 # Ensure that stdout is inherited from the parent

Callers

nothing calls this directly

Calls 4

waitMethod · 0.95
assertEqualMethod · 0.45
startMethod · 0.45
joinMethod · 0.45

Tested by

no test coverage detected