aborting commands for an update. Move update_pending to the start of
the update sequence where the commands are aborted.
#include "ioqueue.h"
#include "empio.h"
#include "gen.h" /* getfdtablesize */
+#include "server.h"
#include "empthread.h"
{
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;
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);
mob_plane(etu);
mob_land(etu);
}
- update_pending = 1;
player->proc = empth_self();
player->cnum = 0;
player->god = 1;
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)
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
dp = player_new(0, 0);
if (!dp) {
logerror("can't create dummy player for update");
+ update_pending = 0;
continue;
}
stacksize = 100000 +