1
0
Fork 0
mirror of https://github.com/albfan/miraclecast.git synced 2025-03-09 23:38:56 +00:00

wpas: drain input-queues before signalling HUP

We _must_ aggressively drain input queues before we signal any HUP. There
might be queued messages that tell us important information about the
termination of wpa_supplicant.

Therefore, if a write() operation fails, we only signal HUP if the input
queues are empty. However, we cannot rely on EPOLLIN to be set, as the
input data might have arrived in between epoll_wait() and write(),
therefore, always run the non-blocking read() in case write() failed.

Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
This commit is contained in:
David Herrmann 2014-03-28 12:40:17 +01:00
parent fc02c0aaf6
commit 9fdda3b09a

View file

@ -1411,18 +1411,27 @@ static int wpas__read(struct wpas *w)
static int wpas_io_fn(sd_event_source *source, int fd, uint32_t mask, void *d) static int wpas_io_fn(sd_event_source *source, int fd, uint32_t mask, void *d)
{ {
struct wpas *w = d; struct wpas *w = d;
int r; int r, write_r;
/* make sure WPAS stays around during any user-callbacks */ /* make sure WPAS stays around during any user-callbacks */
wpas_ref(w); wpas_ref(w);
/*
* If writing fails, there might still be messages in the in-queue even
* though EPOLLIN might not have been set, yet. So in any case, if
* writing failed, try reading some left-overs from the queue. Only if
* the queue is empty, we handle any possible write-errors.
*/
if (mask & EPOLLOUT) { if (mask & EPOLLOUT) {
r = wpas__write(w); write_r = wpas__write(w);
if (r < 0 && r != -EAGAIN) if (write_r == -EAGAIN)
goto error; write_r = 0;
} else {
write_r = 0;
} }
if (mask & EPOLLIN) { if (mask & EPOLLIN || write_r < 0) {
/* Read one packet from the FD and return. Don't block the /* Read one packet from the FD and return. Don't block the
* event loop by reading in a loop. We're called again if * event loop by reading in a loop. We're called again if
* there's still data so make sure higher priority tasks will * there's still data so make sure higher priority tasks will
@ -1431,7 +1440,7 @@ static int wpas_io_fn(sd_event_source *source, int fd, uint32_t mask, void *d)
if (r < 0 && r != -EAGAIN) if (r < 0 && r != -EAGAIN)
goto error; goto error;
/* Iff EPOLLIN was set, there definitely was data in the queue /* If EPOLLIN was set, there definitely was data in the queue
* and there *might* be more. So always return here instead of * and there *might* be more. So always return here instead of
* falling back to EPOLLHUP below. The next iteration will read * falling back to EPOLLHUP below. The next iteration will read
* remaining data and once EPOLLIN is no longer set, we will * remaining data and once EPOLLIN is no longer set, we will
@ -1440,7 +1449,9 @@ static int wpas_io_fn(sd_event_source *source, int fd, uint32_t mask, void *d)
goto out; goto out;
} }
if (mask & (EPOLLHUP | EPOLLERR)) /* If we got here with an error, there definitely is no data left in
* the input-queue. We can finally handle the HUP and be done. */
if (mask & (EPOLLHUP | EPOLLERR) || write_r < 0)
goto error; goto error;
goto out; goto out;