class_docstr: ForkedProcess is a substitute for Process that uses os.fork() to generate a new process.
  This is much faster than starting a completely new interpreter and child processes
  automatically have a copy of the entire program state from before the fork. This
  makes it an appealing approach when parallelizing expensive computations. (see
  also Parallelizer)
  
  However, fork() comes with some caveats and limitations:
  
    - fork() is not available on Windows.
    - It is not possible to have a QApplication in both parent and child process
      (unless both QApplications are created _after_ the call to fork())
      Attempts by the forked process to access Qt GUI elements created by the parent
      will most likely cause the child to crash.
    - Likewise, database connections are unlikely to function correctly in a forked child.
    - Threads are not copied by fork(); the new process
      will have only one thread that starts wherever fork() was called in the parent process.
    - Forked processes are unceremoniously terminated when join() is called; they are not
      given any opportunity to clean up. (This prevents them calling any cleanup code that
      was only intended to be used by the parent process)
    - Normally when fork()ing, open file handles are shared with the parent process,
      which is potentially dangerous. ForkedProcess is careful to close all file handles
      that are not explicitly needed--stdout, stderr, and a single pipe to the parent
      process.
    
docstr: When initializing, an optional target may be given. 
  If no target is specified, self.eventLoop will be used.
  If None is given, no target will be called (and it will be up 
  to the caller to properly shut down the forked process)
  
  preProxy may be a dict of values that will appear as ObjectProxy
  in the remote process (but do not need to be sent explicitly since 
  they are available immediately before the call to fork().
  Proxies will be availabe as self.proxies[name].
  
  If randomReseed is True, the built-in random and numpy.random generators
  will be reseeded in the child process.
docstr_tok: ["When","initializing",",","an","optional","target","may","be","given",".","If","no","target","is","specified",",","self.eventLoop","will","be","used",".","If","None","is","given",",","no","target","will","be","called","(","and","it","will","be","up","to","the","caller","to","properly","shut","down","the","forked","process",")","preProxy","may","be","a","dict","of","values","that","will","appear","as","ObjectProxy","in","the","remote","process","(","but","do","not","need","to","be","sent","explicitly","since","they","are","available","immediately","before","the","call","to","fork","(",")",".","Proxies","will","be","availabe","as","self.proxies","[","name","]",".","If","randomReseed","is","True",",","the","built-in","random","and","numpy.random","generators","will","be","reseeded","in","the","child","process","."]
code: def __init__(
      self, name=None, target=0, preProxy=None, randomReseed=True
  ):
      """
      When initializing, an optional target may be given.
      If no target is specified, self.eventLoop will be used.
      If None is given, no target will be called (and it will be up
      to the caller to properly shut down the forked process)
  
      preProxy may be a dict of values that will appear as ObjectProxy
      in the remote process (but do not need to be sent explicitly since
      they are available immediately before the call to fork().
      Proxies will be availabe as self.proxies[name].
  
      If randomReseed is True, the built-in random and numpy.random generators
      will be reseeded in the child process.
      """
      self.hasJoined = False
      if target == 0:
          target = self.eventLoop
      if name is None:
          name = str(self)
  
      conn, remoteConn = multiprocessing.Pipe()
  
      proxyIDs = {}
      if preProxy is not None:
          for k, v in preProxy.items():
              proxyId = LocalObjectProxy.registerObject(v)
              proxyIDs[k] = proxyId
  
      ppid = (
          os.getpid()
      )  # write this down now; windows doesn't have getppid
      pid = os.fork()
      if pid == 0:
          self.isParent = False
          ## We are now in the forked process; need to be extra careful what we touch while here.
          ##   - no reading/writing file handles/sockets owned by parent process (stdout is ok)
          ##   - don't touch QtGui or QApplication at all; these are landmines.
          ##   - don't let the process call exit handlers
  
          os.setpgrp()  ## prevents signals (notably keyboard interrupt) being forwarded from parent to this process
  
          ## close all file handles we do not want shared with parent
          conn.close()
          sys.stdin.close()  ## otherwise we screw with interactive prompts.
          fid = remoteConn.fileno()
          os.closerange(3, fid)
          os.closerange(
              fid + 1, 4096
          )  ## just guessing on the maximum descriptor count..
  
          ## Override any custom exception hooks
          def excepthook(*args):
              import traceback
  
              traceback.print_exception(*args)
  
          sys.excepthook = excepthook
  
          ## Make it harder to access QApplication instance
          for qtlib in ("PyQt4", "PySide", "PyQt5"):
              if qtlib in sys.modules:
                  sys.modules[qtlib + ".QtGui"].QApplication = None
                  sys.modules.pop(qtlib + ".QtGui", None)
                  sys.modules.pop(qtlib + ".QtCore", None)
  
          ## sabotage atexit callbacks
          atexit._exithandlers = []
          atexit.register(lambda: os._exit(0))
  
          if randomReseed:
              if "numpy.random" in sys.modules:
                  sys.modules["numpy.random"].seed(
                      os.getpid() ^ int(time.time() * 10000 % 10000)
                  )
              if "random" in sys.modules:
                  sys.modules["random"].seed(
                      os.getpid() ^ int(time.time() * 10000 % 10000)
                  )
  
          # ppid = 0 if not hasattr(os, 'getppid') else os.getppid()
          RemoteEventHandler.__init__(
              self, remoteConn, name + "_child", pid=ppid
          )
  
          self.forkedProxies = {}
          for name, proxyId in proxyIDs.items():
              self.forkedProxies[name] = ObjectProxy(
                  ppid, proxyId=proxyId, typeStr=repr(preProxy[name])
              )
  
          if target is not None:
              target()
  
      else:
          self.isParent = True
          self.childPid = pid
          remoteConn.close()
          RemoteEventHandler.handlers = (
              {}
          )  ## don't want to inherit any of this from the parent.
  
          RemoteEventHandler.__init__(
              self, conn, name + "_parent", pid=pid
          )
          atexit.register(self.join)
  
imports: import atexit
  import inspect
  import multiprocessing.connection
  import os
  import signal
  import subprocess
  import sys
  import time
  import pickle
  from ..Qt import QT_LIB, mkQApp
  from ..util import cprint
  from .remoteproxy import ClosedError, LocalObjectProxy, NoResultError, ObjectProxy, RemoteEventHandler
  import threading
label_desc: Use image node_id 1 to create a new ForkedProcess object from inherited base classes: RemoteEventHandler with example: obj = ForkedProcess(name, target, preProxy, randomReseed)