Issue 23309: Hang on interpreter shutdown if daemon thread prints to stdout (original) (raw)

A script spawning a single daemon thread calling print() in a loop (like the attached) will usually hang on shutdown in Python 3.4.2 and hg rev 8d802fb6ae32. Attaching gdb at that point shows the following:

(gdb) thread apply all bt

Thread 1 (Thread 0x7fd927d58700 (LWP 30274)): #0 sem_wait () at ../sysdeps/unix/sysv/linux/x86_64/sem_wait.S:85 #1 0x00000000005282fe in PyThread_acquire_lock_timed (lock=0x1c5ea30, microseconds=microseconds@entry=-1, intr_flag=intr_flag@entry=0) at Python/thread_pthread.h:352 #2 0x0000000000528414 in PyThread_acquire_lock (lock=, waitflag=waitflag@entry=1) at Python/thread_pthread.h:556 #3 0x0000000000567e4c in _enter_buffered_busy (self=0x7fd927bc2b48) at ./Modules/_io/bufferedio.c:327 #4 buffered_flush (self=0x7fd927bc2b48, args=) at ./Modules/_io/bufferedio.c:874 #5 0x000000000042822a in PyObject_Call (func=0x7fd9277b69d8, arg=, kw=) at Objects/abstract.c:2086 #6 0x00000000004290e4 in call_function_tail (args=0x7fd927b8d048, callable=0x7fd9277b69d8) at Objects/abstract.c:2124 #7 callmethod (is_size_t=1, va=0x7fff5c6cf6b0, format=0x0, func=0x7fd9277b69d8) at Objects/abstract.c:2193 #8 _PyObject_CallMethodId_SizeT (o=, name=, format=0x0) at Objects/abstract.c:2279 #9 0x000000000042822a in PyObject_Call (func=0x7fd9277b6990, arg=, kw=) at Objects/abstract.c:2086 #10 0x0000000000428cc4 in call_function_tail (args=0x7fd927b8d048, callable=0x7fd9277b6990) at Objects/abstract.c:2124 #11 callmethod (is_size_t=0, va=0x7fff5c6cf7e0, format=0x5b9924 "", func=0x7fd9277b6990) at Objects/abstract.c:2193 #12 _PyObject_CallMethodId (o=o@entry=0x7fd927b5d3a8, name=name@entry=0x862b00 , format=format@entry=0x5b9924 "") at Objects/abstract.c:2238 #13 0x000000000050a521 in flush_std_files () at Python/pylifecycle.c:488 #14 0x000000000050a5aa in Py_Finalize () at Python/pylifecycle.c:550 #15 0x000000000041fc92 in Py_Main (argc=-1, argv=0x1) at Modules/main.c:787 #16 0x000000000041be3c in main (argc=2, argv=) at ./Programs/python.c:69

The daemon thread has exited, and the main thread hangs trying to flush stdout.

I haven't fully tracked down what happens here, but I think it's this:

If that is what happens, I don't really see how to fix it (it's an example of daemon threads not releasing their resources, which the documentation warns about). But it's obviously unfortunate if merely writing to stdout/err is such a resource.

I'm afraid I don't have real-world code I can confirm is fixed, since I reported this on behalf of someone on irc in #python.

I think I'd prefer the Py_FatalError version of the patch. It's definitely possible to see writes to stdout/stderr at this time. If I read the first version right, it'll succeed the ENTER_BUFFERED without actually grabbing the lock, which seems problematic. But failing ENTER_BUFFERED is probably also more problematic, as it will probably lead to another exception that Python'll try to write to stderr, which fails the same way... If stdout/stderr are in a broken state during shutdown, Python is probably better off calling Py_FatalError rather than intermittently discarding messages.