# Buggy code
def wait_for_exit(runner: Runner, main_process: Popen) -> None:
    """
    Monitor main process and background items until done
    """
    runner.write("Everything launched. Waiting to exit...")
    main_command = str_command(str(arg) for arg in main_process.args)
    span = runner.span()
    while True:
        sleep(0.1)
        main_code = main_process.poll()
        if main_code is not None:
            # Shell exited, we're done. Automatic shutdown cleanup will kill
            # subprocesses.
            runner.write(
                "Main process ({})\n exited with code {}.".format(
                    main_command, main_code
                )
            )
            span.end()
            runner.set_success(True)
            raise SystemExit(main_code)
        dead_bg = runner.tracked.which_dead()
        if dead_bg:
            # Unfortunately torsocks doesn't deal well with connections
            # being lost, so best we can do is shut down.
            # FIXME: Look at bg.critical and do something smarter
            runner.show(
                "Proxy to Kubernetes exited. This is typically due to"
                " a lost connection."
            )
            span.end()
            raise runner.fail("Exiting...", code=3)


# Traceback (AttributeError)
9.7  25 | [INFO  tini (1)] Spawned child process 'python3' with pid '8'
9.9  25 |    0.0 TEL | Telepresence 0+unknown launched at Wed Aug 22 21:04:45 2018
9.9  25 |    0.0 TEL |   /usr/bin/entrypoint.py proxy '{"port": 58856, "cidrs": ["10.3.240.0/20", "10.0.17.0/24", "10.0.1.0/24", "10.0.0.0/24", "10.0.2.0/24"], "expose_ports": [], "ip": "198.18.0.254"}'
9.9  25 |    0.0 TEL | Platform: linux
9.9  25 |    0.0 TEL | Python 3.6.1 (default, Oct  2 2017, 20:46:59)
9.9  25 |    0.0 TEL | [GCC 6.3.0]
9.9  25 |    0.0 TEL | [1] Running: uname -a
9.9  25 |    0.0   1 | Linux 868d9a9b63da 4.9.93-linuxkit-aufs #1 SMP Wed Jun 6 16:55:56 UTC 2018 x86_64 Linux
9.9  25 |    0.0 TEL | Everything launched. Waiting to exit...
9.9  25 |    0.0 TEL | BEGIN SPAN __init__.py:497(wait_for_exit)
10.0  25 | Traceback (most recent call last):
10.0  25 |   File "/usr/bin/entrypoint.py", line 121, in <module>
10.0  25 |     main()
10.0  25 |   File "/usr/bin/entrypoint.py", line 65, in main
10.0  25 |     proxy(loads(sys.argv[2]))
10.0  25 |   File "/usr/bin/entrypoint.py", line 104, in proxy
10.0  25 |     wait_for_exit(runner, main_process)
10.0  25 |   File "/usr/lib/python3.6/site-packages/telepresence/runner/__init__.py", line 512, in wait_for_exit
10.0  25 |     dead_bg = runner.tracked.which_dead()
10.0  25 | AttributeError: 'NoneType' object has no attribute 'which_dead'
10.0  25 | [INFO  tini (1)] Main child exited normally (with status '1')

# Fixed code
def wait_for_exit(runner: Runner, main_process: Popen) -> None:
    """
    Monitor main process and background items until done
    """
    runner.write("Everything launched. Waiting to exit...")
    main_command = str_command(str(arg) for arg in main_process.args)
    span = runner.span()
    while True:
        sleep(0.1)
        main_code = main_process.poll()
        if main_code is not None:
            # Shell exited, we're done. Automatic shutdown cleanup will kill
            # subprocesses.
            runner.write(
                "Main process ({})\n exited with code {}.".format(
                    main_command, main_code
                )
            )
            span.end()
            runner.set_success(True)
            raise SystemExit(main_code)
        if runner.tracked:
            dead_bg = runner.tracked.which_dead()
        else:
            dead_bg = None
        if dead_bg:
            # Unfortunately torsocks doesn't deal well with connections
            # being lost, so best we can do is shut down.
            # FIXME: Look at bg.critical and do something smarter
            runner.show(
                "Proxy to Kubernetes exited. This is typically due to"
                " a lost connection."
            )
            span.end()
            raise runner.fail("Exiting...", code=3)