From 5ce099f6717479dad4c293583caf5568c9d729e6 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Sun, 11 Mar 2012 10:06:04 +0100 Subject: [PATCH] Fix io_close() to obey deadline for output, too A client can delay thread exit indefinitely by not reading output. Broken in commit 08b94556 (v4.3.20) "Reimplement max_idle without a separate thread". Until then, the idle thread aborted a stuck attempt to flush output. Denial of service seems possible. Note that commit 904822e3 moved flushing the output queue from player_login() to io_close(). It also made io_close() wait for the client to close the connection. That wait obeys the deadline. --- src/lib/empthread/io.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/lib/empthread/io.c b/src/lib/empthread/io.c index af6b97dcf..0a44916d7 100644 --- a/src/lib/empthread/io.c +++ b/src/lib/empthread/io.c @@ -105,6 +105,16 @@ io_open(int fd, int flags, int bufsize) return iop; } +/* + * Close IOP. + * Flush output and wait for the client to close the connection. + * Wait at most until DEADLINE. (time_t)-1 means wait as long as it + * takes (no timeout). + * Both the flush and the wait can be separately cut short by + * empth_wakeup(). This is almost certainly not what you want. If + * you need early wakeup, better fix this function not to go to sleep + * after wakeup during flush. + */ void io_close(struct iop *iop, time_t deadline) { @@ -112,7 +122,7 @@ io_close(struct iop *iop, time_t deadline) char buf[IO_BUFSIZE]; int ret; - while (io_output(iop, (time_t)-1) > 0) ; + while (io_output(iop, deadline) > 0) ; shutdown(iop->fd, SHUT_WR); while (empth_select(iop->fd, EMPTH_FD_READ, io_timeout(&timeout, deadline)) > 0) { -- 2.43.0