docs: def run(function_name=None, function_input=None):
      """Triggers the execution environment entry point processor.
  
      Use this function in the program entry point code:
  
      .. code-block:: python
  
         import dxpy
  
         @dxpy.entry_point('main')
         def hello(i):
             pass
  
         dxpy.run()
  
      This method may be used to invoke the program either in a production
      environment (inside the execution environment) or for local
      debugging (in the debug harness), as follows:
  
      If the environment variable *DX_JOB_ID* is set, the processor
      retrieves the job with that ID from the API server. The job's
      *function* field indicates the function name to be invoked. That
      function name is looked up in the table of all methods decorated
      with *@dxpy.entry_point('name')* in the module from which
      :func:`run()` was called, and the matching method is invoked (with
      the job's input supplied as parameters). This is the mode of
      operation used in the DNAnexus execution environment.
  
      .. warning::
  
         The parameters *function_name* and *function_input* are
         disregarded in this mode of operation.
  
      If the environment variable *DX_JOB_ID* is not set, the function
      name may be given in *function_name*; if not set, it is set by the
      environment variable *DX_TEST_FUNCTION*. The function input may be
      given in *function_input*; if not set, it is set by the local file
      *job_input.json* which is expected to be present.
  
      The absence of *DX_JOB_ID* signals to :func:`run()` that execution
      is happening in the debug harness. In this mode of operation, all
      calls to :func:`dxpy.bindings.dxjob.new_dxjob()` (and higher level
      handler methods which use it) are intercepted, and :func:`run()` is
      invoked instead with appropriate inputs.
  
      """
  
      global RUN_COUNT
      RUN_COUNT += 1
  
      dx_working_dir = os.getcwd()
  
      if dxpy.JOB_ID is not None:
          logging.basicConfig()
  
          try:
              logging.getLogger().addHandler(dxpy.DXLogHandler())
          except dxpy.exceptions.DXError:
              print("TODO: FIXME: the EE client should die if logging is not available")
  
          job = dxpy.describe(dxpy.JOB_ID)
      else:
          if function_name is None:
              function_name = os.environ.get('DX_TEST_FUNCTION', 'main')
          if function_input is None:
              with open("job_input.json", "r") as fh:
                  function_input = json.load(fh)
  
          job = {'function': function_name, 'input': function_input}
  
      with open("job_error_reserved_space", "w") as fh:
          fh.write("This file contains reserved space for writing job errors in case the filesystem becomes full.\n" + " "*1024*64)
  
      print("Invoking", job.get('function'), "with", job.get('input'))
  
      try:
          result = ENTRY_POINT_TABLE[job['function']](**job['input'])
      except dxpy.AppError as e:
          save_error(e, dx_working_dir, error_type="AppError")
          raise
      except Exception as e:
          save_error(e, dx_working_dir)
          raise
  
      if result is not None:
          # TODO: protect against client removing its original working directory
          os.chdir(dx_working_dir)
          if USING_PYTHON2:
              # On python-2 we need to use binary mode
              with open("job_output.json", "wb") as fh:
                  json.dump(result, fh, indent=2, cls=DXJSONEncoder)
                  fh.write(b"\n")
          else:
              with open("job_output.json", "w") as fh:
                  json.dump(result, fh, indent=2, cls=DXJSONEncoder)
                  fh.write("\n")
  
      return result