# Buggy code
def spawn_debuggee(session, start_request, sudo, args, console, console_title):
    cmdline = ["sudo"] if sudo else []
    cmdline += [sys.executable, os.path.dirname(launcher.__file__)]
    cmdline += args
    env = {}

    def spawn_launcher():
        with session.accept_connection_from_launcher() as (_, launcher_port):
            env[str("DEBUGPY_LAUNCHER_PORT")] = str(launcher_port)
            if log.log_dir is not None:
                env[str("DEBUGPY_LOG_DIR")] = compat.filename_str(log.log_dir)
            if log.stderr.levels != {"warning", "error"}:
                env[str("DEBUGPY_LOG_STDERR")] = str(" ".join(log.stderr.levels))

            if console == "internalConsole":
                log.info("{0} spawning launcher: {1!r}", session, cmdline)

                # If we are talking to the IDE over stdio, sys.stdin and sys.stdout are
                # redirected to avoid mangling the DAP message stream. Make sure the
                # launcher also respects that.
                subprocess.Popen(
                    cmdline,
                    env=dict(list(os.environ.items()) + list(env.items())),
                    stdin=sys.stdin,
                    stdout=sys.stdout,
                    stderr=sys.stderr,
                )

            else:
                log.info('{0} spawning launcher via "runInTerminal" request.', session)
                session.ide.capabilities.require("supportsRunInTerminalRequest")
                kinds = {
                    "integratedTerminal": "integrated",
                    "externalTerminal": "external",
                }
                session.ide.channel.request(
                    "runInTerminal",
                    {
                        "kind": kinds[console],
                        "title": console_title,
                        "args": cmdline,
                        "env": env,
                    },
                )

        try:
            session.launcher.channel.request(start_request.command, arguments)
        except messaging.MessageHandlingError as exc:
            exc.propagate(start_request)

    if session.no_debug:
        arguments = start_request.arguments
        spawn_launcher()
    else:
        _, port = servers.Connection.listener.getsockname()
        arguments = dict(start_request.arguments)
        arguments["port"] = port
        arguments["clientAccessToken"] = adapter.access_token
        spawn_launcher()

        if not session.wait_for(
            lambda: session.launcher is not None and session.launcher.pid is not None,
            timeout=5,
        ):
            raise start_request.cant_handle(
                '{0} timed out waiting for "process" event from {1}',
                session,
                session.launcher,
            )

        # Wait for the first incoming connection regardless of the PID - it won't
        # necessarily match due to the use of stubs like py.exe or "conda run".
        conn = servers.wait_for_connection(session, lambda conn: True, timeout=10)
        if conn is None:
            raise start_request.cant_handle(
                "{0} timed out waiting for debuggee to spawn", session
            )
        conn.attach_to_session(session)


# Traceback (ConnectionRefusedError)
C:\Python37\python.exe c:\Users\kanadig\.vscode\extensions\ms-python.python-2020.2.60897-dev\pythonFiles\lib\python\new_ptvsd\wheels\ptvsd\launcher C:\GIT\issues\issue9214/test_mp.py
Could not connect to 127.0.0.1: 50734
Traceback (most recent call last):
File "c:\Users\kanadig\.vscode\extensions\ms-python.python-2020.2.60897-dev\pythonFiles\lib\python\new_ptvsd\wheels\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 514, in start_client
s.connect((host, port))
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "c:\Users\kanadig\.vscode\extensions\ms-python.python-2020.2.60897-dev\pythonFiles\lib\python\new_ptvsd\wheels\ptvsd\_vendored\pydevd\pydevd.py", line 2550, in settrace
client_access_token,
File "c:\Users\kanadig\.vscode\extensions\ms-python.python-2020.2.60897-dev\pythonFiles\lib\python\new_ptvsd\wheels\ptvsd\_vendored\pydevd\pydevd.py", line 2610, in _locked_settrace
py_db.connect(host, port)  # Note: connect can raise error.
File "c:\Users\kanadig\.vscode\extensions\ms-python.python-2020.2.60897-dev\pythonFiles\lib\python\new_ptvsd\wheels\ptvsd\_vendored\pydevd\pydevd.py", line 1179, in connect
s = start_client(host, port)
File "c:\Users\kanadig\.vscode\extensions\ms-python.python-2020.2.60897-dev\pythonFiles\lib\python\new_ptvsd\wheels\ptvsd\_vendored\pydevd\_pydevd_bundle\pydevd_comm.py", line 514, in start_client
s.connect((host, port))
ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
File "C:\Python37\lib\concurrent\futures\process.py", line 102, in _python_exit
thread_wakeup.wakeup()
File "C:\Python37\lib\concurrent\futures\process.py", line 90, in wakeup
self._writer.send_bytes(b"")
File "C:\Python37\lib\multiprocessing\connection.py", line 183, in send_bytes
self._check_closed()
File "C:\Python37\lib\multiprocessing\connection.py", line 136, in _check_closed
raise OSError("handle is closed")
OSError: handle is closed

# Fixed code
def spawn_debuggee(session, start_request, sudo, args, console, console_title):
    cmdline = ["sudo"] if sudo else []
    cmdline += [sys.executable, os.path.dirname(launcher.__file__)]
    cmdline += args
    env = {}

    arguments = dict(start_request.arguments)
    if not session.no_debug:
        _, arguments["port"] = servers.listener.getsockname()
        arguments["clientAccessToken"] = adapter.access_token

    def on_launcher_connected(sock):
        listener.close()
        stream = messaging.JsonIOStream.from_socket(sock)
        Launcher(session, stream)

    listener = sockets.serve("Launcher", on_launcher_connected, "127.0.0.1", backlog=0)
    try:
        _, launcher_port = listener.getsockname()

        env[str("DEBUGPY_LAUNCHER_PORT")] = str(launcher_port)
        if log.log_dir is not None:
            env[str("DEBUGPY_LOG_DIR")] = compat.filename_str(log.log_dir)
        if log.stderr.levels != {"warning", "error"}:
            env[str("DEBUGPY_LOG_STDERR")] = str(" ".join(log.stderr.levels))

        if console == "internalConsole":
            log.info("{0} spawning launcher: {1!r}", session, cmdline)

            # If we are talking to the IDE over stdio, sys.stdin and sys.stdout are
            # redirected to avoid mangling the DAP message stream. Make sure the
            # launcher also respects that.
            subprocess.Popen(
                cmdline,
                env=dict(list(os.environ.items()) + list(env.items())),
                stdin=sys.stdin,
                stdout=sys.stdout,
                stderr=sys.stderr,
            )

        else:
            log.info('{0} spawning launcher via "runInTerminal" request.', session)
            session.ide.capabilities.require("supportsRunInTerminalRequest")
            kinds = {
                "integratedTerminal": "integrated",
                "externalTerminal": "external",
            }
            session.ide.channel.request(
                "runInTerminal",
                {
                    "kind": kinds[console],
                    "title": console_title,
                    "args": cmdline,
                    "env": env,
                },
            )

        if not session.wait_for(lambda: session.launcher, timeout=10):
            raise start_request.cant_handle(
                "{0} timed out waiting for {1} to connect",
                session,
                session.launcher,
            )

        try:
            session.launcher.channel.request(start_request.command, arguments)
        except messaging.MessageHandlingError as exc:
            exc.propagate(start_request)

        if session.no_debug:
            return

        if not session.wait_for(lambda: session.launcher.pid is not None, timeout=10):
            raise start_request.cant_handle(
                '{0} timed out waiting for "process" event from {1}',
                session,
                session.launcher,
            )

        # Wait for the first incoming connection regardless of the PID - it won't
        # necessarily match due to the use of stubs like py.exe or "conda run".
        conn = servers.wait_for_connection(session, lambda conn: True, timeout=10)
        if conn is None:
            raise start_request.cant_handle(
                "{0} timed out waiting for debuggee to spawn", session
            )
        conn.attach_to_session(session)

    finally:
        listener.close()