def _fork(self, path, uid, gid, executable, args, environment, **kwargs):
        """
        Fork and then exec sub-process.

        @param path: the path where to run the new process.
        @type path: L{bytes} or L{unicode}
        @param uid: if defined, the uid used to run the new process.
        @type uid: L{int}
        @param gid: if defined, the gid used to run the new process.
        @type gid: L{int}
        @param executable: the executable to run in a new process.
        @type executable: L{str}
        @param args: arguments used to create the new process.
        @type args: L{list}.
        @param environment: environment used for the new process.
        @type environment: L{dict}.
        @param kwargs: keyword arguments to L{_setupChild} method.
        """
        collectorEnabled = gc.isenabled()
        gc.disable()
        try:
            self.pid = os.fork()
        except:
            # Still in the parent process
            if collectorEnabled:
                gc.enable()
            raise
        else:
            if self.pid == 0:
                # A return value of 0 from fork() indicates that we are now
                # executing in the child process.

                # Do not put *ANY* code outside the try block. The child
                # process must either exec or _exit. If it gets outside this
                # block (due to an exception that is not handled here, but
                # which might be handled higher up), there will be two copies
                # of the parent running in parallel, doing all kinds of damage.

                # After each change to this code, review it to make sure there
                # are no exit paths.

                try:
                    # Stop debugging. If I am, I don't care anymore.
                    sys.settrace(None)
                    self._setupChild(**kwargs)
                    self._execChild(path, uid, gid, executable, args,
                                    environment)
                except:
                    # If there are errors, try to write something descriptive
                    # to stderr before exiting.

                    # The parent's stderr isn't *necessarily* fd 2 anymore, or
                    # even still available; however, even libc assumes that
                    # write(2, err) is a useful thing to attempt.

                    try:
                        stderr = os.fdopen(2, 'wb')
                        msg = ("Upon execvpe {0} {1} in environment id {2}"
                               "\n:").format(executable, str(args),
                                             id(environment))

                        if _PY3:

                            # On Python 3, print_exc takes a text stream, but
                            # on Python 2 it still takes a byte stream.  So on
                            # Python 3 we will wrap up the byte stream returned
                            # by os.fdopen using TextIOWrapper.

                            # We hard-code UTF-8 as the encoding here, rather
                            # than looking at something like
                            # getfilesystemencoding() or sys.stderr.encoding,
                            # because we want an encoding that will be able to
                            # encode the full range of code points.  We are
                            # (most likely) talking to the parent process on
                            # the other end of this pipe and not the filesystem
                            # or the original sys.stderr, so there's no point
                            # in trying to match the encoding of one of those
                            # objects.

                            stderr = io.TextIOWrapper(stderr, encoding="utf-8")

                        stderr.write(msg)
                        traceback.print_exc(file=stderr)
                        stderr.flush()

                        for fd in range(3):
                            os.close(fd)
                    except:
                        # Handle all errors during the error-reporting process
                        # silently to ensure that the child terminates.
                        pass

                # See comment above about making sure that we reach this line
                # of code.
                os._exit(1)

        # we are now in parent process
        if collectorEnabled:
            gc.enable()
        self.status = -1 # this records the exit status of the child

        Fork and then exec sub-process.

        @param path: the path where to run the new process.
        @type path: L{bytes} or L{unicode}
        @param uid: if defined, the uid used to run the new process.
        @type uid: L{int}
        @param gid: if defined, the gid used to run the new process.
        @type gid: L{int}
        @param executable: the executable to run in a new process.
        @type executable: L{str}
        @param args: arguments used to create the new process.
        @type args: L{list}.
        @param environment: environment used for the new process.
        @type environment: L{dict}.
        @param kwargs: keyword arguments to L{_setupChild} method.
        
stackoverflow/venv/lib/python3.6/site-packages/twisted/internet/process.py