[Mesa-dev] [PATCH] util/queue: don't hang at exit

Nicolai Hähnle nhaehnle at gmail.com
Tue Apr 18 10:56:00 UTC 2017


On 18.04.2017 03:34, Rob Clark wrote:
> 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 at 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 at 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=<optimized out>) 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=<optimized out>) at ../../../../../src/gallium/drivers/freedreno/freedreno_context.c:54
>  #9  0x0000007fb6b43294 in st_glFlush (ctx=<optimized out>) at ../../../src/mesa/state_tracker/st_cb_flush.c:121
>  #10 0x0000007fb69a84e8 in _mesa_make_current (newCtx=newCtx at entry=0x0, drawBuffer=drawBuffer at entry=0x0, readBuffer=readBuffer at entry=0x0) at ../../../src/mesa/main/context.c:1654
>  #11 0x0000007fb6b7ca58 in st_api_make_current (stapi=<optimized out>, stctxi=0x0, stdrawi=0x0, streadi=0x0) at ../../../src/mesa/state_tracker/st_manager.c:827
>  #12 0x0000007fb6cc87e8 in dri_unbind_context (cPriv=<optimized out>) 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

OMGWTF. What a hilarious mess of atexit code running at various times.


> Fixes: 4aea8fe7 ("gallium/u_queue: fix random crashes when the app calls exit()")
> Signed-off-by: Rob Clark <robdclark at gmail.com>
> ---
>  src/util/u_queue.c | 11 ++++++++++-
>  1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/src/util/u_queue.c b/src/util/u_queue.c
> index 0519667..8db09b0 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..
> +       */

I think this comment should explicitly say something like "this should 
only happen when an application makes driver calls from an atexit handler".

Since that's a pretty messed up thing to do, even if piglit does it, I 
think this workaround is fine.

Reviewed-by: Nicolai Hähnle <nicolai.haehnle at amd.com>


> +      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 */
>


-- 
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.


More information about the mesa-dev mailing list