Okay, I know why your code doesn't exit: It's because internally the poll_read
function uses tokio_threadpool::blocking
to mark that it is entering a blocking section of code.
Internally the way the threadpool in tokio worked at that time was that it had a small number of threads used for running asynchronous code, but it would also have up to 100 threads dedicated to just running blocking operations such as reading from a file. Since both kinds of threads were part of the same threadpool, it can even change the role of a thread: When a thread enters a blocking section, it will just switch its role to be a thread for blocking operations and go back when leaving it.
This means that calls to poll_read
will not return NotReady
if data isn't ready yet. The thread is just moved into the fleet of blocking threads for the duration of the blocking operation. The only situation where poll_read
would return NotReady
would be if the thread pool already had 100 threads in that state.
I am unsure how exactly tokio works now, but this is why your asynchronous code is about the same as synchronous code. The only thing is that your code would fail if it somehow hit that 100 thread threshold.