Both have to do with the test runner's handling of the tests. With one
it's the read thread somehow outliving the other threads (e.g. with
ctrl-C). The other is due to a filled OS-level pipe's buffer causing a
block while code is still holding the GIL in some gRPC core function. We
can't empty the buffer from Python because the GIL is held, and the OS
can't unblock because it's waiting for the buffer to get cleared:
deadlock.
This reorganizes the Python code, scraps the current testing
infrastructure, and implements a simple test discovery and run script
based on the standard Python unittest library so we can trust that our
tests are running.