[PATCH 2/2] os/connection: Remove NewOutputPending

Jeremy Huddleston Sequoia jeremyhu at apple.com
Sun Sep 18 17:56:26 UTC 2016


> On Sep 18, 2016, at 08:51, Keith Packard <keithp at keithp.com> wrote:
> 
> Jeremy Huddleston Sequoia <jeremyhu at apple.com> writes:
> 
>> Use any_output_pending() instead.
> 
> These aren't equivalent -- NewOutputPending is set when there is output
> pending and we haven't detected that all of the clients with output
> are blocked.

The comment says that NewOutputPending is set when there is output that hasn't been attempted yet, which is slightly different.  The usage doesn't match the name/comment, so it is a tad confusing trying to see where it should or should not be set.

> There's a patch for a bug in FlushAllOutput to set NewOutputPending when
> we skip a client that has pending input. I attached that to my previous
> message in this thread.
> 
> I think an alternative would be to remove write blocked clients from the
> output pending list and re-add them when they became writable
> again. Then we could use any_output_pending() instead of NewOutputPending.

Yeah, I was not liking the behavior of "something is ready, so try everything" that NewOutputPending is part of.

I like the idea of only iterating over a list of clients that are expected to be unblocked.

---

> On Sep 18, 2016, at 08:42, Keith Packard <keithp at keithp.com> wrote:
> 
> Jeremy Huddleston Sequoia <jeremyhu at apple.com> writes:
> 
>> On encountering an EAGAIN, FlushClient() re-adds the client to the
>> pending list and returns, but FlushClient() doesn't get called again.
>> We would expect it to be called via FlushAllOutput() via
>> WaitForSomething(), but that only happens when NewOutputPending is
>> set.  FlushAllOutput() also early-exits if NewOutputPending is not
>> set.
>> 
>> The only place that is setting NewOutputPending is ClientReady().  The
>> problem there is that ClientReady() is called based on an edge trigger
>> and not a level trigger.
> 
> Hrm. I think this is a problem with our emulation of edge triggers as we
> don't tell the ospoll layer when we've detected that the client is not
> writable.
> 
> This should fix that; it makes the edge re-trigger whenever we start
> listening again:
> 
> diff --git a/os/ospoll.c b/os/ospoll.c
> index b00d422..8c99501 100644
> --- a/os/ospoll.c
> +++ b/os/ospoll.c
> @@ -352,10 +352,14 @@ ospoll_listen(struct ospoll *ospoll, int fd, int xevents)
>         epoll_mod(ospoll, osfd);
> #endif
> #if POLL
> -        if (xevents & X_NOTIFY_READ)
> +        if (xevents & X_NOTIFY_READ) {
>             ospoll->fds[pos].events |= POLLIN;
> -        if (xevents & X_NOTIFY_WRITE)
> +            ospoll->fds[pos].revents &= ~POLLIN;
> +        }
> +        if (xevents & X_NOTIFY_WRITE) {
>             ospoll->fds[pos].events |= POLLOUT;
> +            ospoll->fds[pos].revents &= ~POLLOUT;
> +        }
> #endif
>     }
> }
> 
> I did find a bug with the NewOutputPending flag. We don't actually flush
> the client's buffer if there are still requests queued. This is a change
> From the previous behavior.
> 
> diff --git a/os/io.c b/os/io.c
> index ff0ec3d..c6db028 100644
> --- a/os/io.c
> +++ b/os/io.c
> @@ -615,6 +615,8 @@ FlushAllOutput(void)
>         if (!client_is_ready(client)) {
>             oc = (OsCommPtr) client->osPrivate;
>             (void) FlushClient(client, oc, (char *) NULL, 0);
> +        } else {
> +            NewOutputPending = TRUE;
>         }
>     }
> }

The issue remains with just these two changes applied.

In my particular case, !client_is_ready(client), so we're not hitting that second bug, but yes, it would definitely be an issue.

IMO, it would be best to not have a NewOutputPending boolean at all and base it solely on the list of pending clients (with the optimization of removing EWOULDBLOCK clients until they are ready for data).

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 4465 bytes
Desc: not available
URL: <https://lists.x.org/archives/xorg-devel/attachments/20160918/f9b3461d/attachment.bin>


More information about the xorg-devel mailing list