fork_wait.py 2.2 KB

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