blob: 713039dd82687210fbf4d9d11c0717fbc41344bb [file] [log] [blame]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001"""This test case provides support for checking forking and wait behavior.
2
Victor Stinner45df8202010-04-28 22:31:17 +00003To test different wait behavior, override the wait_impl method.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00004
5We want fork1() semantics -- only the forking thread survives in the
6child after a fork().
7
8On some systems (e.g. Solaris without posix threads) we find that all
9active threads survive in the child after a fork(); this is an error.
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000010"""
11
Victor Stinner45df8202010-04-28 22:31:17 +000012import os, sys, time, unittest
13import test.support as support
14_thread = support.import_module('_thread')
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000015
16LONGSLEEP = 2
17SHORTSLEEP = 0.5
18NUM_THREADS = 4
19
20class ForkWait(unittest.TestCase):
21
22 def setUp(self):
23 self.alive = {}
24 self.stop = 0
25
26 def f(self, id):
27 while not self.stop:
28 self.alive[id] = os.getpid()
29 try:
30 time.sleep(SHORTSLEEP)
Andrew Svetlovf7a17b42012-12-25 16:47:37 +020031 except OSError:
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000032 pass
33
34 def wait_impl(self, cpid):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000035 for i in range(10):
36 # waitpid() shouldn't hang, but some of the buildbots seem to hang
37 # in the forking tests. This is an attempt to fix the problem.
38 spid, status = os.waitpid(cpid, os.WNOHANG)
39 if spid == cpid:
40 break
41 time.sleep(2 * SHORTSLEEP)
42
Ezio Melottib3aedd42010-11-20 19:04:17 +000043 self.assertEqual(spid, cpid)
44 self.assertEqual(status, 0, "cause = %d, exit = %d" % (status&0xff, status>>8))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000045
Antoine Pitrou606c3f52011-05-09 21:17:02 +020046 @support.reap_threads
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000047 def test_wait(self):
48 for i in range(NUM_THREADS):
Georg Brandl2067bfd2008-05-25 13:05:15 +000049 _thread.start_new(self.f, (i,))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000050
Victor Stinner1e48eb32014-03-18 00:39:04 +010051 # busy-loop to wait for threads
52 deadline = time.monotonic() + 10.0
53 while len(self.alive) < NUM_THREADS:
54 time.sleep(0.1)
Victor Stinner8231d552014-09-04 01:02:17 +020055 if deadline < time.monotonic():
Victor Stinner1e48eb32014-03-18 00:39:04 +010056 break
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000057
Guido van Rossumcc2b0162007-02-11 06:12:03 +000058 a = sorted(self.alive.keys())
Ezio Melottib3aedd42010-11-20 19:04:17 +000059 self.assertEqual(a, list(range(NUM_THREADS)))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000060
61 prefork_lives = self.alive.copy()
62
63 if sys.platform in ['unixware7']:
64 cpid = os.fork1()
65 else:
66 cpid = os.fork()
67
68 if cpid == 0:
69 # Child
70 time.sleep(LONGSLEEP)
71 n = 0
72 for key in self.alive:
73 if self.alive[key] != prefork_lives[key]:
74 n += 1
75 os._exit(n)
76 else:
77 # Parent
Antoine Pitrou606c3f52011-05-09 21:17:02 +020078 try:
79 self.wait_impl(cpid)
80 finally:
81 # Tell threads to die
82 self.stop = 1