"xdump updates" believes there are always 15 (UPDATE_TIME_LEN - 1)
scheduled updates. When fewer than 15 updates are scheduled, it shows
whatever crap update time happens to be in the unused part of
update_time[]: the initial zero or a previously scheduled update.
Root cause is that table EF_UPDATES has always UPDATE_TIME_LEN - 1
entries, which is incorrect when fewer updates are scheduled. Only
xdump is affected, as the other users ignore the length and stop at
the sentinel.
Fix update_get_schedule() to resize table EF_UPDATES.
Why upgrade? I'm not a lawyer, but here's my take on the differences
to version 2:
* Software patents: better protection against abuse of patents to
prevent users from exercising the rights under the GPL. I doubt
we'll get hit with a patent suit, but it's a good move just on
general principles.
* License compatibility: compatible with more free licenses, i.e. can
"steal" more free software for use in Empire. I don't expect to steal
much, but it's nice to have the option.
* Definition of "source code": modernization of some details for today's
networked world, to make it easier to distribute the software. Not
really relevant to us now, as we normally distribute full source code.
* Tivoization: this is about putting GPL-licensed software in hardware,
then make the hardware refuse to run modified software. "Neat" trick
to effectively deny its users their rights under the GPL. Abuse was
"pioneered" by TiVo (popular digital video recorders). GPLv3 forbids
it. Unlikely to become a problem for us.
* Internationalization: more careful wording, to harden the license
outside the US. The lawyers tell us it better be done that way.
* License violations: friendlier way to deal with license violations.
This has come out of past experience enforcing the GPL.
* Additional permissions: Probably not relevant to us.
Also include myself in the list of principal authors.
This is so we can avoid linking utilities with socket libraries (see
commit 8b778634).
When using sockets, we need to replace close(), because Windows'
close() can't cope with socket file descriptors. But replacing it
always would pull in the socket stuff again. Define close() to call
function pointer w32_close_function, which is initially _close.
Rename posix_close() to w32_close_maybe_socket(). Make new
w32_socket_init() put it in w32_close_function.
Same for read() and write(): define read(), write() to call function
pointers w32_read_function, w32_write_function, initially _read(),
_write(); rename posix_read(), posix_write() to
w32_read_maybe_socket(), w32_write_maybe_socket(), and put them into
w32_read_function, w32_write_function in w32_socket_init().
Also call WSAStartup() there, and use that from loc_NTInit().
WSACleanup() now belongs next to w32_socket_init(). Don't bother,
just drop it, along with loc_NTTerm().
start_server() creates the thread running player_accept() before it
calls update_init(). However, update_init() initializes stuff used to
player threads: update_time[] and play_lock. In theory, a player
thread could start before that, and crash when taking the
uninitialized play_lock.
Delay starting that tread until after update_init().
A player thread may sleep on input or output, except:
(1) While it is executing a C_MOD command, it may only sleep on input.
(2) While it is being aborted by the update or shutdown, it may not
sleep at all.
To find out whether a player thread may sleep on input, code has to
check condition (2). It needs do to that in recvclient().
To find out whether it may sleep on output, it has to check both
conditions. It needs to do that in pr_player() and upr_player().
The code tracked condition (1) in global variable play_lock_wanted.
It checked condition (2) by examining struct player member command.
Replace all that by new struct player member may_sleep. Initialize it
in player_new(), update it in dispatch(), shutdwn() and update_run().
This makes the tests in recvclient(), pr_player() and upr_player()
obvious. play_wrlock_wanted() is now unused, remove it.
Crash dump forks a child to call abort(). abort() may flush or close
streams. This is unwelcome, because it can mess up streams in the
parent. Observed with the journal. Could theoretically also affect
commands info, read, turn, and wire; announcement expiry, and reading
of econfig and schedule.
Fix by using SIGABRT instead.
Note that flushing streams before fork() is not a sufficient fix,
because closing a stream can still move the file descriptor's file
position. Do it anyway, to ensure any buffered output is visible to
post_crash_dump_hook.
Remove the KillIdle thread. Add timeout to struct iop, initialized in
io_open(). Obey it in io_input() by passing it to empth_select(). If
empth_select() times out, report that back through io_input() to
recvclient() and player_login(). If player_login() receives a timeout
indication, print a message and terminate the session. If
recvclient() receives a timeout indication, flash a message to the
player and initiate a shut down the player's session.
Create WIN32 sys/time.h to define struct timeval. This creates some
conflicts with WIN32 windows.h definitions. Including windows.h in
show.c and info.c creates conflicts, so remove that. Modify service.c
to include sys/socket.h instead of windows.h to remove the conflict
with sys/time.h.
Change oops() to call the new oops_handler function pointer instead of
offering a fixed set of actions. Change server's main() to install a
handler for the action requested by -E.
Three options: abort, crash-dump, nothing. crash-dump works by
aborting a fork. It isn't implemented for Windows.
The oops action is no longer tied to daemon mode, but -d still implies
-E abort for convenience.
Split ef_init() into two functions: empfile_init() for initialization,
and empfile_fixup() to fix it up for configuration. Put them next to
empfile[]. Move the call to empfile_init() from behind emp_config()
to before it.
read_builtin_tables() wanted to run in builtindir, and
read_custom_tables() wanted to run in configdir. Bothersome. Use new
fopenat() to relax those requirements.
The chdir() satisfying them are now superflous, remove them.
Until now, they tried to recover and continue (debug off). That's
appropriate only for the server. The server could be told to abort
instead (debug on, selected by option -d), but not the utility
programs.
Change debug to be on by default, and switch it off early in the
server's main(). No functional change for the server.
a seed for the random function.
(nightlybuild.sh): Add the -R 1 for the server.
(nightlybuild.sh): Switch to -R 1 for the fairland as 1 is safer.
Some systems might generate lousy randomness from a
zero seed.
(prng.patch): Not required anymore, -R 1 is used instead.
(main, emp_server.6): Rename -r and -R to -u and -U. "-R" is now used for random seed.
flawed. Firstly, when player_kill_idle() ran before the player thread
could react to being aborted by update or shutdown, player_kill_idle()
incorrectly diagnosed it as hung. Secondly, terminating hung threads
leaks resources and can leave a stale play_lock behind. It could
perhaps even corrupt game state. It might salvage some scenarios, but
makes others worse. Not worth it.
supports priorities. Update synchronization used to rely on them,
which naturally worked only with LWP (#1504036). With that fixed, no
uses of priorities remained, but a minor bug did: players could starve
out threads with priorities below PP_PLAYER, i.e. delete_lostitems()
and player_kill_idle(). Closes#1458175:
(empth_create): Remove parameter prio. Callers changed. Also gets
rid of misleading comments in pthread.c and ntthread.c.
(PP_MAIN, PP_UPDATE, PP_SHUTDOWN, PP_SCHED, PP_TIMESTAMP, PP_PLAYER)
(PP_ACCEPT, PP_KILLIDLE): Remove.
(empth_init, empth_create) [EMPTH_LWP]: Pass priority 1.