diff --git a/src/lib/gen/io.c b/src/lib/gen/io.c index 389cfc88..bf77d0f2 100644 --- a/src/lib/gen/io.c +++ b/src/lib/gen/io.c @@ -62,6 +62,7 @@ #include "ioqueue.h" #include "empio.h" #include "gen.h" /* getfdtablesize */ +#include "server.h" #include "empthread.h" @@ -337,7 +338,11 @@ io_output_all(struct iop *iop) { int n; - while ((n = io_output(iop, IO_NOWAIT)) > 0) { + /* + * Mustn't block a player thread while update is pending, or else + * a malicous player could delay the update indefinitely + */ + while (((n = io_output(iop, IO_NOWAIT)) > 0) && !update_pending) { empth_select(iop->fd, EMPTH_FD_WRITE); } return n; diff --git a/src/lib/update/main.c b/src/lib/update/main.c index 0c265e2d..c1ebf886 100644 --- a/src/lib/update/main.c +++ b/src/lib/update/main.c @@ -74,6 +74,9 @@ update_main(void *unused) struct natstr *cnp; struct natstr *np; + if (CANT_HAPPEN(!update_pending)) + update_pending = 1; + /* First, make sure all mobility is updated correctly. */ if (opt_MOB_ACCESS) { mob_ship(etu); @@ -81,7 +84,6 @@ update_main(void *unused) mob_plane(etu); mob_land(etu); } - update_pending = 1; player->proc = empth_self(); player->cnum = 0; player->god = 1; diff --git a/src/server/update.c b/src/server/update.c index 015747f6..f4026bd4 100644 --- a/src/server/update.c +++ b/src/server/update.c @@ -120,6 +120,7 @@ update_wait(void *unused) while (1) { empth_sem_wait(update_sem); + update_pending = 1; running = 0; for (p = player_next(0); p != 0; p = player_next(p)) { if (p->state != PS_PLAYING) @@ -137,8 +138,10 @@ update_wait(void *unused) empth_sleep(now + 2); } if (*pre_update_hook) { - if (run_hook(pre_update_hook, "pre-update")) + if (run_hook(pre_update_hook, "pre-update")) { + update_pending = 0; continue; + } } /* * we rely on the fact that update's priority is the highest @@ -147,6 +150,7 @@ update_wait(void *unused) dp = player_new(0, 0); if (!dp) { logerror("can't create dummy player for update"); + update_pending = 0; continue; } stacksize = 100000 +