def spawn(self, args, executable=None, stdin=None, stdout=None, stderr=None,
              shell=False, cwd=None, env=None, flags=0, extra_handles=None):
        """Spawn a new child process.

        The executable to spawn and its arguments are determined by *args*,
        *executable* and *shell*.

        When *shell* is set to ``False`` (the default), *args* is normally a
        sequence and it contains both the program to execute (at index 0), and
        its arguments.

        When *shell* is set to ``True``, then *args* is normally a string and
        it indicates the command to execute through the shell.

        The *executable* argument can be used to override the executable to
        execute. If *shell* is ``False``, it overrides ``args[0]``. This is
        sometimes used on Unix to implement "fat" executables that behave
        differently based on argv[0]. If *shell* is ``True``, it overrides the
        shell to use. The default shell is ``'/bin/sh'`` on Unix, and the value
        of $COMSPEC (or ``'cmd.exe'`` if it is unset) on Windows.

        The *stdin*, *stdout* and *stderr* arguments specify how to handle
        standard input, output, and error, respectively. If set to None, then
        the child will inherit our respective stdio handle. If set to the
        special constant ``PIPE`` then a pipe is created. The pipe will be
        connected to a :class:`gruvi.StreamProtocol` which you can use to read
        or write from it. The stream protocol instance is available under
        either :attr:`stdin`, :attr:`stdout` or :attr:`stderr`. All 3 stdio
        arguments can also be a file descriptor, a file-like object, or a pyuv
        ``Stream`` instance.

        The *extra_handles* specifies any extra handles to pass to the client.
        It must be a sequence where each element is either a file descriptor, a
        file-like objects, or a ``pyuv.Stream`` instance. The position in the
        sequence determines the file descriptor in the client. The first
        position corresponds to FD 3, the second to 4, etc. This places these
        file descriptors directly after the stdio handles.

        The *cwd* argument specifies the directory to change to before
        executing the child. If not provided, the current directory is used.

        The *env* argument specifies the environment to use when executing the
        child. If provided, it must be a dictionary. By default, the current
        environment is used.

        The *flags* argument can be used to specify optional libuv
        ``uv_process_flags``. The only relevant flags are
        ``pyuv.UV_PROCESS_DETACHED`` and ``pyuv.UV_PROCESS_WINDOWS_HIDE``. Both
        are Windows specific and are silently ignored on Unix.
        """
        if self._process:
            raise RuntimeError('child process already spawned')
        self._child_exited.clear()
        self._closed.clear()
        self._exit_status = None
        self._term_signal = None
        hub = get_hub()
        if isinstance(args, str):
            args = [args]
            flags |= pyuv.UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS
        else:
            args = list(args)
        if shell:
            if hasattr(os, 'fork'):
                # Unix
                if executable is None:
                    executable = '/bin/sh'
                args = [executable, '-c'] + args
            else:
                # Windows
                if executable is None:
                    executable = os.environ.get('COMSPEC', 'cmd.exe')
                args = [executable, '/c'] + args
        if executable is None:
            executable = args[0]
        kwargs = {}
        if env is not None:
            kwargs['env'] = env
        if cwd is not None:
            kwargs['cwd'] = cwd
        kwargs['flags'] = flags
        handles = self._get_child_handles(hub.loop, stdin, stdout, stderr, extra_handles)
        kwargs['stdio'] = handles
        process = pyuv.Process.spawn(hub.loop, args, executable,
                                     exit_callback=self._on_child_exit, **kwargs)
        # Create stdin/stdout/stderr transports/protocols.
        if handles[0].stream:
            self._stdin = self._connect_child_handle(handles[0])
        if handles[1].stream:
            self._stdout = self._connect_child_handle(handles[1])
        if handles[2].stream:
            self._stderr = self._connect_child_handle(handles[2])
        self._process = process
Spawn a new child process.

        The executable to spawn and its arguments are determined by *args*,
        *executable* and *shell*.

        When *shell* is set to ``False`` (the default), *args* is normally a
        sequence and it contains both the program to execute (at index 0), and
        its arguments.

        When *shell* is set to ``True``, then *args* is normally a string and
        it indicates the command to execute through the shell.

        The *executable* argument can be used to override the executable to
        execute. If *shell* is ``False``, it overrides ``args[0]``. This is
        sometimes used on Unix to implement "fat" executables that behave
        differently based on argv[0]. If *shell* is ``True``, it overrides the
        shell to use. The default shell is ``'/bin/sh'`` on Unix, and the value
        of $COMSPEC (or ``'cmd.exe'`` if it is unset) on Windows.

        The *stdin*, *stdout* and *stderr* arguments specify how to handle
        standard input, output, and error, respectively. If set to None, then
        the child will inherit our respective stdio handle. If set to the
        special constant ``PIPE`` then a pipe is created. The pipe will be
        connected to a :class:`gruvi.StreamProtocol` which you can use to read
        or write from it. The stream protocol instance is available under
        either :attr:`stdin`, :attr:`stdout` or :attr:`stderr`. All 3 stdio
        arguments can also be a file descriptor, a file-like object, or a pyuv
        ``Stream`` instance.

        The *extra_handles* specifies any extra handles to pass to the client.
        It must be a sequence where each element is either a file descriptor, a
        file-like objects, or a ``pyuv.Stream`` instance. The position in the
        sequence determines the file descriptor in the client. The first
        position corresponds to FD 3, the second to 4, etc. This places these
        file descriptors directly after the stdio handles.

        The *cwd* argument specifies the directory to change to before
        executing the child. If not provided, the current directory is used.

        The *env* argument specifies the environment to use when executing the
        child. If provided, it must be a dictionary. By default, the current
        environment is used.

        The *flags* argument can be used to specify optional libuv
        ``uv_process_flags``. The only relevant flags are
        ``pyuv.UV_PROCESS_DETACHED`` and ``pyuv.UV_PROCESS_WINDOWS_HIDE``. Both
        are Windows specific and are silently ignored on Unix.