code: def _launch(self, process_obj):
      logger.debug("%s %s _launch called", process_obj, self)
  
      if config.ipc_active:
          logger.debug(
              "%s ipc_active is set, launch background thread", self
          )
          self.launch_fiber_background_thread_if_needed()
      else:
          logger.debug("%s ipc_active is not set", self)
  
      # Setup networking
      ident = next(_event_counter)
      self.ident = ident
      # this needs to happen after self._setup_listen where port is decided
      global admin_host, admin_port
      if config.ipc_active:
          # in active mode, port is admin_port which could be 0 at first and
          # set to the actual port by the backend thread
          port = admin_port
      else:
          # in passive mode, port can't be 0 because this need to be
          # pre-determined information between master and workers.
          assert self.worker_port != 0, (
              "port can't be 0 because this "
              "need to be pre-determined information between master "
              "and workers."
          )
          port = self.worker_port
  
      if config.ipc_active:
          assert admin_host is not None
          assert admin_port is not None
  
      cmd = self.get_command_line(
          cwd=os.getcwd(), host=admin_host, port=port, id=ident
      )
  
      job = self._get_job(cmd)
  
      event = threading.Event()
      event.clear()
      _event_dict[ident] = event
      logger.debug(
          "%s popen_fiber_spawn created event %s and set _event_dict[%s]",
          self,
          event,
          ident,
      )
  
      # prepare data and serialize
      prep_data = spawn.get_preparation_data(process_obj.name)
      prep_data["fiber_config"] = config.get_object()
      # TODO(jiale) what is a better way to setup sys_path inside containers?
      prep_data.pop("sys_path", None)
      logger.debug("%s prep_data: %s", self, str(prep_data))
      fp = io.BytesIO()
      set_spawning_popen(self)
      try:
          self._pickle_data(prep_data, fp)
          self._pickle_data(process_obj, fp)
      finally:
          set_spawning_popen(None)
  
      # Set process_obj._popen = self here so that we have have the
      # Process <-> Popen binding before _run_job() is called. After
      # _run_job() is called, we started a job with Fiber backend. So
      # Process <-> Popen has to exist so that Process.terminate() can
      # find Popen object and terminate the underlying job. Also, when
      # we serize process_obj above, we have to make sure that
      # Process <-> Popen binding doesn't exist so that Popen doesn't get
      # serialized becuase 1) it's not necessary and 2) some part of Popen
      # cannot be pickled.
      process_obj._popen = self
  
      # launch job
      job = self._run_job(job)
      self.pid = get_pid_from_jid(job.jid)
      # Fix process obj's pid
      process_obj.ident = self.pid
      post_data = {"pid": self.pid}
      self._pickle_data(post_data, fp)
  
      send_buffer = fp.getbuffer()
  
      if config.ipc_active:
          # (worker) active mode, wait for event to be set by
          # background thread
          done = False
          while not done:
              if self._exiting:
                  logger.debug(
                      "process is exiting, don't wait for job to "
                      "connect back"
                  )
                  return
              done = event.wait(0.5)
              status = self.check_status()
              if status == ProcessStatus.STOPPED:
                  return
  
          logger.debug(
              "popen_fiber_spawn is waiting for accept event %s to finish",
              event,
          )
          conn = _event_dict[ident]
          logger.debug("got conn from _event_counter[%s]", ident)
          del _event_dict[ident]
          logger.debug("remove entry _event_counter[%s]", ident)
      else:
          # (worker) passive mode, check job status until it's ready
          while True:
              if self._exiting:
                  logger.debug(
                      "process is exiting, don't wait for job to start"
                  )
                  return
              status = self.check_status()
              if status == ProcessStatus.STARTED:
                  break
              logger.debug(
                  "waiting 1s for job to start, current status: %s",
                  status,
              )
              time.sleep(1)
          # connect to woker job
          if job.host is None:
              job.update()
          ip = job.host
          port = self.worker_port
          addr = (ip, port)
  
          conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
          while True:
              if self._exiting:
                  logger.debug(
                      "process is exiting, don't try to connect to the job"
                  )
                  return
              try:
                  logger.debug("connecting to %s", addr)
                  conn.connect(addr)
              except ConnectionRefusedError:
                  # not ready yet, sleep
                  logger.debug(
                      "Fiber worker is not up yet, waiting 1s for the "
                      "worker to listen on admin address: %s",
                      addr,
                  )
                  time.sleep(1)
                  continue
              break
  
      logger.debug("send buffer")
      conn.send(send_buffer)
  
      # logger.debug("sent fp.getbuffer() to sub process")
  
      self.sentinel = conn
      logger.debug("_launch finished")
  
imports: import fcntl
  import io
  import itertools
  import logging
  import multiprocessing
  import os
  import socket
  import struct
  import subprocess
  import sys
  import threading
  import time
  from multiprocessing import reduction, spawn, util
  from multiprocessing.context import set_spawning_popen
  import cloudpickle
  import requests
  import fiber.util
  import fiber.config
  from fiber.backend import get_backend
  from fiber.core import JobSpec
  from fiber.core import ProcessStatus
label_desc: Use image node_id 13 for calling the Popen obj's underlying member method code with example usage: obj._launch(process_obj) without return types