(root)/
Python-3.12.0/
Lib/
test/
test_fork1.py
       1  """This test checks for correct fork() behavior.
       2  """
       3  
       4  import _imp as imp
       5  import os
       6  import signal
       7  import sys
       8  import threading
       9  import time
      10  import unittest
      11  
      12  from test.fork_wait import ForkWait
      13  from test import support
      14  
      15  
      16  # Skip test if fork does not exist.
      17  if not support.has_fork_support:
      18      raise unittest.SkipTest("test module requires working os.fork")
      19  
      20  
      21  class ESC[4;38;5;81mForkTest(ESC[4;38;5;149mForkWait):
      22      def test_threaded_import_lock_fork(self):
      23          """Check fork() in main thread works while a subthread is doing an import"""
      24          import_started = threading.Event()
      25          fake_module_name = "fake test module"
      26          partial_module = "partial"
      27          complete_module = "complete"
      28          def importer():
      29              imp.acquire_lock()
      30              sys.modules[fake_module_name] = partial_module
      31              import_started.set()
      32              time.sleep(0.01) # Give the other thread time to try and acquire.
      33              sys.modules[fake_module_name] = complete_module
      34              imp.release_lock()
      35          t = threading.Thread(target=importer)
      36          t.start()
      37          import_started.wait()
      38          exitcode = 42
      39          pid = os.fork()
      40          try:
      41              # PyOS_BeforeFork should have waited for the import to complete
      42              # before forking, so the child can recreate the import lock
      43              # correctly, but also won't see a partially initialised module
      44              if not pid:
      45                  m = __import__(fake_module_name)
      46                  if m == complete_module:
      47                      os._exit(exitcode)
      48                  else:
      49                      if support.verbose > 1:
      50                          print("Child encountered partial module")
      51                      os._exit(1)
      52              else:
      53                  t.join()
      54                  # Exitcode 1 means the child got a partial module (bad.) No
      55                  # exitcode (but a hang, which manifests as 'got pid 0')
      56                  # means the child deadlocked (also bad.)
      57                  self.wait_impl(pid, exitcode=exitcode)
      58          finally:
      59              try:
      60                  os.kill(pid, signal.SIGKILL)
      61              except OSError:
      62                  pass
      63  
      64  
      65      def test_nested_import_lock_fork(self):
      66          """Check fork() in main thread works while the main thread is doing an import"""
      67          exitcode = 42
      68          # Issue 9573: this used to trigger RuntimeError in the child process
      69          def fork_with_import_lock(level):
      70              release = 0
      71              in_child = False
      72              try:
      73                  try:
      74                      for i in range(level):
      75                          imp.acquire_lock()
      76                          release += 1
      77                      pid = os.fork()
      78                      in_child = not pid
      79                  finally:
      80                      for i in range(release):
      81                          imp.release_lock()
      82              except RuntimeError:
      83                  if in_child:
      84                      if support.verbose > 1:
      85                          print("RuntimeError in child")
      86                      os._exit(1)
      87                  raise
      88              if in_child:
      89                  os._exit(exitcode)
      90              self.wait_impl(pid, exitcode=exitcode)
      91  
      92          # Check this works with various levels of nested
      93          # import in the main thread
      94          for level in range(5):
      95              fork_with_import_lock(level)
      96  
      97  
      98  def tearDownModule():
      99      support.reap_children()
     100  
     101  if __name__ == "__main__":
     102      unittest.main()