From: Rob Clark Date: Tue, 18 Apr 2017 01:20:37 +0000 (-0400) Subject: util/queue: don't hang at exit X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6fb7935dedc87ffd767a2999f402ce1a46d18cce;p=mesa.git util/queue: don't hang at exit So atexit() is horrible and 4aea8fe7 is probably not a good idea. But add an extra layer of duct-tape to the problem. Otherwise we hit a situation where app using an atexit() handler that runs later than ours doesn't hang when trying to tear down a context. (gdb) bt #0 util_queue_killall_and_wait (queue=queue@entry=0x52bc80) at ../../../src/util/u_queue.c:264 #1 0x0000007fb6c380c0 in atexit_handler () at ../../../src/util/u_queue.c:51 #2 0x0000007fb7730e2c in __run_exit_handlers () from /lib64/libc.so.6 #3 0x0000007fb7730e5c in exit () from /lib64/libc.so.6 #4 0x0000007fb7ce17dc in piglit_report_result (result=PIGLIT_PASS) at /home/robclark/src/piglit/tests/util/piglit-util.c:267 #5 0x0000007fb7ef99f8 in process_next_event (x11_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_x11_framework.c:139 #6 0x0000007fb7ef9a90 in enter_event_loop (winsys_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_x11_framework.c:153 #7 0x0000007fb7ef8e50 in run_test (gl_fw=0x432c20, argc=1, argv=0x7ffffff588) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_winsys_framework.c:88 #8 0x0000007fb7edb890 in piglit_gl_test_run (argc=1, argv=0x7ffffff588, config=0x7ffffff400) at /home/robclark/src/piglit/tests/util/piglit-framework-gl.c:203 #9 0x0000000000401224 in main (argc=1, argv=0x7ffffff588) at /home/robclark/src/piglit/tests/bugs/drawbuffer-modes.c:46 (gdb) c Continuing. [Thread 0x7fb67580c0 (LWP 3471) exited] ^C Thread 1 "drawbuffer-mode" received signal SIGINT, Interrupt. 0x0000007fb72dda34 in pthread_cond_wait@@GLIBC_2.17 () from /lib64/libpthread.so.0 (gdb) bt #0 0x0000007fb72dda34 in pthread_cond_wait@@GLIBC_2.17 () from /lib64/libpthread.so.0 #1 0x0000007fb6c38304 in cnd_wait (mtx=0x5bdc90, cond=0x5bdcc0) at ../../../include/c11/threads_posix.h:159 #2 util_queue_fence_wait (fence=0x5bdc90) at ../../../src/util/u_queue.c:106 #3 0x0000007fb6daac70 in fd_batch_sync (batch=0x5bdc70) at ../../../../../src/gallium/drivers/freedreno/freedreno_batch.c:233 #4 batch_reset (batch=batch@entry=0x5bdc70) at ../../../../../src/gallium/drivers/freedreno/freedreno_batch.c:183 #5 0x0000007fb6daa5e0 in batch_flush (batch=0x5bdc70) at ../../../../../src/gallium/drivers/freedreno/freedreno_batch.c:290 #6 fd_batch_flush (batch=0x5bdc70, sync=) at ../../../../../src/gallium/drivers/freedreno/freedreno_batch.c:308 #7 0x0000007fb6daba2c in fd_bc_flush (cache=0x461220, ctx=0x52b920) at ../../../../../src/gallium/drivers/freedreno/freedreno_batch_cache.c:141 #8 0x0000007fb6dac954 in fd_context_flush (pctx=0x52b920, fence=0x0, flags=) at ../../../../../src/gallium/drivers/freedreno/freedreno_context.c:54 #9 0x0000007fb6b43294 in st_glFlush (ctx=) at ../../../src/mesa/state_tracker/st_cb_flush.c:121 #10 0x0000007fb69a84e8 in _mesa_make_current (newCtx=newCtx@entry=0x0, drawBuffer=drawBuffer@entry=0x0, readBuffer=readBuffer@entry=0x0) at ../../../src/mesa/main/context.c:1654 #11 0x0000007fb6b7ca58 in st_api_make_current (stapi=, stctxi=0x0, stdrawi=0x0, streadi=0x0) at ../../../src/mesa/state_tracker/st_manager.c:827 #12 0x0000007fb6cc87e8 in dri_unbind_context (cPriv=) at ../../../../../src/gallium/state_trackers/dri/dri_context.c:217 #13 0x0000007fb6cc80b0 in driUnbindContext (pcp=0x5271e0) at ../../../../../../src/mesa/drivers/dri/common/dri_util.c:591 #14 0x0000007fb7d1da08 in MakeContextCurrent (dpy=0x433380, draw=0, read=0, gc_user=0x0) at ../../../src/glx/glxcurrent.c:214 #15 0x0000007fb7a8d5e0 in glx_platform_make_current () from /lib64/libwaffle-1.so.0 #16 0x0000007fb7a894e4 in waffle_make_current () from /lib64/libwaffle-1.so.0 #17 0x0000007fb7ef8c60 in piglit_wfl_framework_teardown (wfl_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_wfl_framework.c:628 #18 0x0000007fb7ef939c in piglit_winsys_framework_teardown (winsys_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_winsys_framework.c:238 #19 0x0000007fb7ef9c30 in destroy (gl_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_x11_framework.c:212 #20 0x0000007fb7edb7c4 in destroy () at /home/robclark/src/piglit/tests/util/piglit-framework-gl.c:184 #21 0x0000007fb7730e2c in __run_exit_handlers () from /lib64/libc.so.6 #22 0x0000007fb7730e5c in exit () from /lib64/libc.so.6 #23 0x0000007fb7ce17dc in piglit_report_result (result=PIGLIT_PASS) at /home/robclark/src/piglit/tests/util/piglit-util.c:267 #24 0x0000007fb7ef99f8 in process_next_event (x11_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_x11_framework.c:139 #25 0x0000007fb7ef9a90 in enter_event_loop (winsys_fw=0x432c20) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_x11_framework.c:153 #26 0x0000007fb7ef8e50 in run_test (gl_fw=0x432c20, argc=1, argv=0x7ffffff588) at /home/robclark/src/piglit/tests/util/piglit-framework-gl/piglit_winsys_framework.c:88 #27 0x0000007fb7edb890 in piglit_gl_test_run (argc=1, argv=0x7ffffff588, config=0x7ffffff400) at /home/robclark/src/piglit/tests/util/piglit-framework-gl.c:203 #28 0x0000000000401224 in main (argc=1, argv=0x7ffffff588) at /home/robclark/src/piglit/tests/bugs/drawbuffer-modes.c:46 (gdb) r Fixes: 4aea8fe7 ("gallium/u_queue: fix random crashes when the app calls exit()") Signed-off-by: Rob Clark Reviewed-by: Nicolai Hähnle --- diff --git a/src/util/u_queue.c b/src/util/u_queue.c index 05196674189..8db09b027c2 100644 --- a/src/util/u_queue.c +++ b/src/util/u_queue.c @@ -298,9 +298,18 @@ util_queue_add_job(struct util_queue *queue, struct util_queue_job *ptr; assert(fence->signalled); - fence->signalled = false; mtx_lock(&queue->lock); + if (queue->kill_threads) { + mtx_unlock(&queue->lock); + /* well no good option here, but any leaks will be + * short-lived as things are shutting down.. + */ + return; + } + + fence->signalled = false; + assert(queue->num_queued >= 0 && queue->num_queued <= queue->max_jobs); /* if the queue is full, wait until there is space */