blob: 3b222a8701ba1d2da1b34b4f097288d621b82299 [file] [log] [blame]
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001"""This test case provides support for checking forking and wait behavior.
2
3To test different wait behavior, overrise the wait_impl method.
4
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.
10
11While BeOS doesn't officially support fork and native threading in
12the same application, the present example should work just fine. DC
13"""
14
15import os, sys, time, thread, unittest
16from test.test_support import TestSkipped
17
18LONGSLEEP = 2
19SHORTSLEEP = 0.5
20NUM_THREADS = 4
21
22class ForkWait(unittest.TestCase):
23
24 def setUp(self):
25 self.alive = {}
26 self.stop = 0
27
28 def f(self, id):
29 while not self.stop:
30 self.alive[id] = os.getpid()
31 try:
32 time.sleep(SHORTSLEEP)
33 except IOError:
34 pass
35
36 def wait_impl(self, cpid):
Thomas Wouters0e3f5912006-08-11 14:57:12 +000037 for i in range(10):
38 # waitpid() shouldn't hang, but some of the buildbots seem to hang
39 # in the forking tests. This is an attempt to fix the problem.
40 spid, status = os.waitpid(cpid, os.WNOHANG)
41 if spid == cpid:
42 break
43 time.sleep(2 * SHORTSLEEP)
44
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000045 self.assertEquals(spid, cpid)
46 self.assertEquals(status, 0, "cause = %d, exit = %d" % (status&0xff, status>>8))
47
48 def test_wait(self):
49 for i in range(NUM_THREADS):
50 thread.start_new(self.f, (i,))
51
52 time.sleep(LONGSLEEP)
53
Guido van Rossumcc2b0162007-02-11 06:12:03 +000054 a = sorted(self.alive.keys())
Guido van Rossum805365e2007-05-07 22:24:25 +000055 self.assertEquals(a, list(range(NUM_THREADS)))
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000056
57 prefork_lives = self.alive.copy()
58
59 if sys.platform in ['unixware7']:
60 cpid = os.fork1()
61 else:
62 cpid = os.fork()
63
64 if cpid == 0:
65 # Child
66 time.sleep(LONGSLEEP)
67 n = 0
68 for key in self.alive:
69 if self.alive[key] != prefork_lives[key]:
70 n += 1
71 os._exit(n)
72 else:
73 # Parent
74 self.wait_impl(cpid)
75 # Tell threads to die
76 self.stop = 1
77 time.sleep(2*SHORTSLEEP) # Wait for threads to die