Thank you for the response! I also got success in joining the threads after creating them. Unfortunately for the way that this code is implemented in the bigger project that I'm working on, making that change would be difficult. This is a good workaround though, and helped narrow the root of error down.
Starting over, without the first change, adding exit 0 at the end still gave me similar errors (though there was 1 success run out of 5).
In case you're interested, what I noticed is for my machine, in order for the code to fail, the first request sent by the user agent has to be in a thread that's joined right after its created. On the second request, thread or non-thread, it will mostly crash (around 98% for me, there were 3-4 runs that worked randomly). That said, a quick workaround I'm implementing right now is sending a simple non-thread GET request just to "plant the seed". Then the subsequent requests in threads or non-threads would run without problems.