docs: def fork_detached_process ():
      """Fork this process, creating a subprocess detached from the current context.
  
      Returns a :class:`pwkit.Holder` instance with information about what
      happened. Its fields are:
  
      whoami
        A string, either "original" or "forked" depending on which process we are.
      pipe
        An open binary file descriptor. It is readable by the original process
        and writable by the forked one. This can be used to pass information
        from the forked process to the one that launched it.
      forkedpid
        The PID of the forked process. Note that this process is *not* a child of
        the original one, so waitpid() and friends may not be used on it.
  
      Example::
  
        from pwkit import cli
  
        info = cli.fork_detached_process ()
        if info.whoami == 'original':
            message = info.pipe.readline ().decode ('utf-8')
            if not len (message):
                cli.die ('forked process (PID %d) appears to have died', info.forkedpid)
            info.pipe.close ()
            print ('forked process said:', message)
        else:
            info.pipe.write ('hello world'.encode ('utf-8'))
            info.pipe.close ()
  
      As always, the *vital* thing to understand is that immediately after a
      call to this function, you have **two** nearly-identical but **entirely
      independent** programs that are now both running simultaneously. Until you
      execute some kind of ``if`` statement, the only difference between the two
      processes is the value of the ``info.whoami`` field and whether
      ``info.pipe`` is readable or writeable.
  
      This function uses :func:`os.fork` twice and also calls :func:`os.setsid`
      in between the two invocations, which creates new session and process
      groups for the forked subprocess. It does *not* perform other operations
      that you might want, such as changing the current directory, dropping
      privileges, closing file descriptors, and so on. For more discussion of
      best practices when it comes to “daemonizing” processes, see (stalled)
      `PEP 3143`_.
  
      .. _PEP 3143: https://www.python.org/dev/peps/pep-3143/
  
      """
      import os, struct
      from .. import Holder
      payload = struct.Struct ('L')
  
      info = Holder ()
      readfd, writefd = os.pipe ()
  
      pid1 = os.fork ()
      if pid1 > 0:
          info.whoami = 'original'
          info.pipe = os.fdopen (readfd, 'rb')
          os.close (writefd)
  
          retcode = os.waitpid (pid1, 0)[1]
          if retcode:
              raise Exception ('child process exited with error code %d' % retcode)
  
          (info.forkedpid,) = payload.unpack (info.pipe.read (payload.size))
      else:
          # We're the intermediate child process. Start new session and process
          # groups, detaching us from TTY signals and whatnot.
          os.setsid ()
  
          pid2 = os.fork ()
          if pid2 > 0:
              # We're the intermediate process; we're all done
              os._exit (0)
  
          # If we get here, we're the detached child process.
          info.whoami = 'forked'
          info.pipe = os.fdopen (writefd, 'wb')
          os.close (readfd)
          info.forkedpid = os.getpid ()
          info.pipe.write (payload.pack (info.forkedpid))
  
      return info