Turns out threading.start() returns before the thread actually starts, so there were situations in which we would start the thread and immediately try to use it before run() happened.