<html>
<head>
<base href="https://bugs.freedesktop.org/" />
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Priority</th>
<td>medium
</td>
</tr>
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW --- - wl_display_roundtrip() seems not thread-safe"
href="https://bugs.freedesktop.org/show_bug.cgi?id=83304">83304</a>
</td>
</tr>
<tr>
<th>Assignee</th>
<td>wayland-bugs@lists.freedesktop.org
</td>
</tr>
<tr>
<th>Summary</th>
<td>wl_display_roundtrip() seems not thread-safe
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Classification</th>
<td>Unclassified
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux (All)
</td>
</tr>
<tr>
<th>Reporter</th>
<td>courmisch@gmail.com
</td>
</tr>
<tr>
<th>Hardware</th>
<td>x86-64 (AMD64)
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Version</th>
<td>1.5.0
</td>
</tr>
<tr>
<th>Component</th>
<td>wayland
</td>
</tr>
<tr>
<th>Product</th>
<td>Wayland
</td>
</tr></table>
<p>
<div>
<pre>Hello,
It seems that calling wl_display_roundtrip() from a thread while another thread
runs the Wayland client "mainloop" is prone to deadlocks. After a while, I
always keep getting the calling thread stuck in wl_display_dispatch_queue()
even though the sync event is already completed.
>From a quick look at the code, the use of the "done" variable seems to lack
memory barriers if the function was intended for use across multiple threads. I
would guess there is a race condition between setting the "done" flag and
wl_display_dispatch_queue().
Now, I don't know if this is supposed to work, or if it is not. But even if it
is not, the lack of explicit warning against it in the documentation would
qualify as a bug in my humble opinion.
This is the program's stack dump (where thread 2 runs the mainloop):
Thread 3 (Thread 0x7f19b3d8f700 (LWP 3112)):
#0 0x00007f19de4de0ed in poll () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007f19dfb6249a in poll () from /usr/lib/x86_64-linux-gnu/libasan.so.1
#2 0x00007f19b38703f0 in poll (__timeout=-1, __nfds=1, __fds=0x7f19b3d8e9c0)
at /usr/include/x86_64-linux-gnu/bits/poll2.h:46
#3 wl_display_dispatch_queue (display=display@entry=0x61400007fc40,
---Type <return> to continue, or q <return> to quit---
queue=queue@entry=0x61400007fd28) at ../src/wayland-client.c:1334
#4 0x00007f19b38704cc in wl_display_dispatch (
display=display@entry=0x61400007fc40) at ../src/wayland-client.c:1414
#5 0x00007f19b387052c in wl_display_roundtrip (display=0x61400007fc40)
at ../src/wayland-client.c:856
#6 0x00007f19b3a81cfe in Display (vd=0x6150000af398, pic=0x6130000a44c0,
subpic=0x0) at ../../../modules/video_output/wl/shm.c:248
#7 0x00007f19dd47128f in vout_display_Display (vd=0x6150000af398,
picture=0x6130000a44c0, subpicture=0x0)
at ../../include/vlc_vout_wrapper.h:57
#8 0x00007f19dd47d64f in ThreadDisplayRenderPicture (vout=0x61a00012af18,
is_forced=false) at ../../src/video_output/video_output.c:1061
#9 0x00007f19dd47e2e3 in ThreadDisplayPicture (vout=0x61a00012af18,
deadline=0x7f19b3d8ede0) at ../../src/video_output/video_output.c:1135
#10 0x00007f19dd48394f in Thread (object=0x61a00012af18)
at ../../src/video_output/video_output.c:1572
#11 0x00007f19de9b50a4 in start_thread (arg=0x7f19b3d8f700)
at pthread_create.c:309
#12 0x00007f19de4e6c2d in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
Thread 2 (Thread 0x7f19b3359700 (LWP 3113)):
#0 0x00007f19de4de0ed in poll () at ../sysdeps/unix/syscall-template.S:81
#1 0x00007f19dfb6249a in poll () from /usr/lib/x86_64-linux-gnu/libasan.so.1
#2 0x00007f19b3663f5e in Thread (data=0x6110001d5f98)
at ../../../modules/video_output/wl/shell_surface.c:77
#3 0x00007f19de9b50a4 in start_thread (arg=0x7f19b3359700)
at pthread_create.c:309
#4 0x00007f19de4e6c2d in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(That was generated with libwayland-client 1.5.0, so no _queue, but the problem
should remain identical.)
Meanwhile, the following ugly work-around solves it for me. But obviously, it
assumes that another thread is processing events to invoke the callback:
----8<--------8<--------8<--------8<--------8<--------8<--------8<----
#include <semaphore.h>
static void done_cb(void *data, struct wl_callback *callback, uint32_t serial)
{
sem_t *done = data;
sem_post(done);
wl_callback_destroy(callback);
(void) serial;
}
static const struct wl_callback_listener sync_cbs =
{
done_cb,
};
static int wl_display_roundtrip_(struct wl_display *display)
{
sem_t done;
struct wl_callback *callback = wl_display_sync(display);
if (callback == NULL)
return -1;
sem_init(&done, 0, 0);
wl_callback_add_listener(callback, &sync_cbs, &done);
wl_display_flush(display);
sem_wait(&done);
sem_destroy(&done);
return 0;
}
---->8-------->8-------->8-------->8-------->8-------->8-------->8----</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are the assignee for the bug.</li>
</ul>
</body>
</html>