[PATCH 2/2] client: wake up sleeping threads on all return paths from read_events
Marek Chalupa
mchqwerty at gmail.com
Thu Aug 28 03:20:44 PDT 2014
Hmm, thinking about that... Maybe this is not the right solution.
Programmer should probably do something like:
do {
ret = wl_display_read_events(display);
} while (ret == 0 && errno == EAGAIN);
to be sure he read the events (or got an error). This patch would force him
to re-run wl_display_prepare_read again
in all threads.
On 28 August 2014 11:32, Marek Chalupa <mchqwerty at gmail.com> wrote:
> In the first place, create a function display_wakeup_threads that
> contains always-repeated pattern: broadcast + increase serial.
>
> Replace the pattern with this function and call this function also
> on return from read_events when wl_connection_read fails with
> EAGAIN (this solves the bug from the test from previous commit).
>
> Now all return paths from read_events are safe and wake up the threads.
> There's a path in wl_display_read_events that do not wake up
> threads - this is the case when last_error is set. But on this
> path are the threads always awake, because every function that can
> set last_error sets it via display_fatal_error (which calls
> display_wakeup_threads).
>
> Signed-off-by: Marek Chalupa <mchqwerty at gmail.com>
> ---
> src/wayland-client.c | 42 +++++++++++++++++++++++++++++-------------
> 1 file changed, 29 insertions(+), 13 deletions(-)
>
> diff --git a/src/wayland-client.c b/src/wayland-client.c
> index 9159ee0..9574cf7 100644
> --- a/src/wayland-client.c
> +++ b/src/wayland-client.c
> @@ -110,6 +110,27 @@ struct wl_display {
> static int debug_client = 0;
>
> /**
> + * This helper function wakes up all threads that are
> + * waiting for display->reader_cond (i. e. when reading is done
> + * canceled, or an error occured)
> + *
> + * NOTE: must be called with display->mutex locked
> + */
> +static void
> +display_wakeup_threads(struct wl_display *display)
> +{
> + pthread_cond_broadcast(&display->reader_cond);
> +
> + /* Thread can get sleeping only in read_events() and if we're
> + * waking it up, it means that the read processed or was
> + * canceled, so we must increase the read_serial.
> + * This prevents from indefinite looping in read_events()
> + * (when calling pthread_cond_wait under condition
> + * display->read_serial == serial). */
> + ++display->read_serial;
> +}
> +
> +/**
> * This function is called for local errors (no memory, server hung up)
> *
> * \param display
> @@ -128,11 +149,7 @@ display_fatal_error(struct wl_display *display, int
> error)
>
> display->last_error = error;
>
> - pthread_cond_broadcast(&display->reader_cond);
> - /* prevent from indefinite looping in read_events()
> - * (when calling pthread_cond_wait under condition
> - * display->read_serial == serial) */
> - ++display->read_serial;
> + display_wakeup_threads(display);
> }
>
> /**
> @@ -182,7 +199,7 @@ display_protocol_error(struct wl_display *display,
> uint32_t code,
> display->protocol_error.interface = intf;
>
> /*
> - * here it is not necessary to broadcast reader's cond like in
> + * here it is not necessary to wake up threads like in
> * display_fatal_error, because this function is called from
> * an event handler and that means that read_events() is done
> * and woke up all threads. Since wl_display_prepare_read()
> @@ -1138,8 +1155,10 @@ read_events(struct wl_display *display)
> if (display->reader_count == 0) {
> total = wl_connection_read(display->connection);
> if (total == -1) {
> - if (errno == EAGAIN)
> + if (errno == EAGAIN) {
> + display_wakeup_threads(display);
> return 0;
> + }
>
> display_fatal_error(display, errno);
> return -1;
> @@ -1162,8 +1181,7 @@ read_events(struct wl_display *display)
> }
> }
>
> - display->read_serial++;
> - pthread_cond_broadcast(&display->reader_cond);
> + display_wakeup_threads(display);
> } else {
> serial = display->read_serial;
> while (display->read_serial == serial)
> @@ -1348,10 +1366,8 @@ wl_display_cancel_read(struct wl_display *display)
> pthread_mutex_lock(&display->mutex);
>
> display->reader_count--;
> - if (display->reader_count == 0) {
> - display->read_serial++;
> - pthread_cond_broadcast(&display->reader_cond);
> - }
> + if (display->reader_count == 0)
> + display_wakeup_threads(display);
>
> pthread_mutex_unlock(&display->mutex);
> }
> --
> 1.9.3
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/wayland-devel/attachments/20140828/3750f323/attachment-0001.html>
More information about the wayland-devel
mailing list