[PATCH 2/2] client: wake up sleeping threads on all return paths from read_events

Marek Chalupa mchqwerty at gmail.com
Fri Aug 29 02:24:27 PDT 2014


This patch is now obsolete, see
http://lists.freedesktop.org/archives/wayland-devel/2014-August/016966.html


On 28 August 2014 12:20, Marek Chalupa <mchqwerty at gmail.com> wrote:

> 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/20140829/9373d9ef/attachment.html>


More information about the wayland-devel mailing list