From: Markus Armbruster Date: Sun, 18 Mar 2012 17:30:39 +0000 (+0100) Subject: Change login command kill to kill less ruthlessly X-Git-Tag: v4.3.30~24 X-Git-Url: http://git.pond.sub.org/?p=empserver;a=commitdiff_plain;h=eb25be08d4812e51bac539494823034a1aaf69bd Change login command kill to kill less ruthlessly The victim's connection closes without any explanation. Output may be lost. This is because kill_cmd() kills by calling io_shutdown(), which shuts down the socket and drains the I/O queues. How this makes the victim's thread terminate is a bit subtle: shutting down the socket makes it ready. If the victim's thread is waiting for I/O, it wakes up. Since all further reads return EOF, and all further writes fail, the command terminates quickly (short of inifinite loop bugs), then the command loop, and finally the thread. To make kill behave more nicely, change kill_cmd() to work exactly like server shutdown: send a flash message to the victim, set his EOF indicator, abort the command, forbid sleeping on I/O, wake up the victim's thread. Just as reliable, but doesn't lose output. If the victim's client fails to close his connection, the victim's thread may still linger in state PS_SHUTDOWN for up to login_grace_time (default 120s). An attacker could try to use that to make the server run out of file descriptors or memory, but simply connecting achieves the same effect more cheaply. --- diff --git a/src/lib/player/login.c b/src/lib/player/login.c index aa0033bee..743739658 100644 --- a/src/lib/player/login.c +++ b/src/lib/player/login.c @@ -381,8 +381,12 @@ kill_cmd(void) return RET_FAIL; } logerror("%s killed country #%d", praddr(player), player->cnum); - io_shutdown(other->iop, IO_READ | IO_WRITE); - pr_id(player, C_EXIT, "closed socket of offending job\n"); + pr_flash(other, "Disconnected by %s\n", praddr(player)); + io_set_eof(other->iop); + other->aborted = 1; + other->may_sleep = PLAYER_SLEEP_NEVER; + empth_wakeup(other->proc); + pr_id(player, C_EXIT, "terminated %s's connection\n", praddr(other)); return RET_OK; }