python (3.11.7)
1 """This test case provides support for checking forking and wait behavior.
2
3 To test different wait behavior, override the wait_impl method.
4
5 We want fork1() semantics -- only the forking thread survives in the
6 child after a fork().
7
8 On some systems (e.g. Solaris without posix threads) we find that all
9 active threads survive in the child after a fork(); this is an error.
10 """
11
12 import os, sys, time, unittest
13 import threading
14 from test import support
15 from test.support import threading_helper
16
17
18 LONGSLEEP = 2
19 SHORTSLEEP = 0.5
20 NUM_THREADS = 4
21
22 class ESC[4;38;5;81mForkWait(ESC[4;38;5;149munittestESC[4;38;5;149m.ESC[4;38;5;149mTestCase):
23
24 def setUp(self):
25 self._threading_key = threading_helper.threading_setup()
26 self.alive = {}
27 self.stop = 0
28 self.threads = []
29
30 def tearDown(self):
31 # Stop threads
32 self.stop = 1
33 for thread in self.threads:
34 thread.join()
35 thread = None
36 self.threads.clear()
37 threading_helper.threading_cleanup(*self._threading_key)
38
39 def f(self, id):
40 while not self.stop:
41 self.alive[id] = os.getpid()
42 try:
43 time.sleep(SHORTSLEEP)
44 except OSError:
45 pass
46
47 def wait_impl(self, cpid, *, exitcode):
48 support.wait_process(cpid, exitcode=exitcode)
49
50 def test_wait(self):
51 for i in range(NUM_THREADS):
52 thread = threading.Thread(target=self.f, args=(i,))
53 thread.start()
54 self.threads.append(thread)
55
56 # busy-loop to wait for threads
57 for _ in support.sleeping_retry(support.SHORT_TIMEOUT, error=False):
58 if len(self.alive) >= NUM_THREADS:
59 break
60
61 a = sorted(self.alive.keys())
62 self.assertEqual(a, list(range(NUM_THREADS)))
63
64 prefork_lives = self.alive.copy()
65
66 if sys.platform in ['unixware7']:
67 cpid = os.fork1()
68 else:
69 cpid = os.fork()
70
71 if cpid == 0:
72 # Child
73 time.sleep(LONGSLEEP)
74 n = 0
75 for key in self.alive:
76 if self.alive[key] != prefork_lives[key]:
77 n += 1
78 os._exit(n)
79 else:
80 # Parent
81 self.wait_impl(cpid, exitcode=0)