The previous commit's message claims the race can lead to duplicated
output, use after free, then double-free. That's correct only up to
the use after free. There is no double-free.
Heap corruption (double-free?) has been observed in Changeling,
though. Player logged in (still in sanctuary), map #, crashed within
removecc()'s free(io->data). Partial backtrace:
raise () from /lib64/libc.so.6
abort () from /lib64/libc.so.6
__libc_message () from /lib64/libc.so.6
malloc_printerr () from /lib64/libc.so.6
removecc (ioq=0x251fd10, cc=468) at ../src/lib/gen/ioqueue.c:350
ioq_dequeue (ioq=0x251fd10, cc=468) at ../src/lib/gen/ioqueue.c:135
io_output (iop=0x251fc90, wait=1) at ../src/lib/empthread/io.c:231
recvclient (cmd=0x258d8e0 "", size=1024) at ../src/lib/player/recvclient.c:82
getcommand (combufp=0x2557068 "map #1") at ../src/lib/player/empdis.c:84
I haven't been able to reproduce.
To hopefully catch ioqueue going south earlier, make ioq_dequeue()
oops when it can't dequeue as many bytes as requested.
Local analysis can now easily find out what's up. Before, inter-
procedural analysis was required. The Clang Static Analyzer
complained about a dereference of res that is actually fine.
Local analysis can now easily find out what's up. Before,
whole-program analysis was required. The Clang Static Analyzer
complained about code that is actually fine.
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.
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.
File names in econfig need to be interpreted relative to configdir.
This wasn't the case everywhere for keys data and info.
Fix this by changing variables gamedir and infodir to hold absolute
names. Change builtindir likewise, for consistency. Store the values
from econfig in gamedir_conf, infodir_conf and builtindir_conf.
Uses new fnameat() to derive absolute names from possibly relative
ones.
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.
Move stuff to untangle the ugly cyclic dependencies between the
archives built for selected subdirectories of src/lib/:
* Move common/io.c to empthread/ because it requires empthread stuff
* Move parts of subs/nstr.c to common/nstreval.c to satisfy
common/ef_verify.o
* Move getstarg.c getstring.c onearg.c from gen/ to subs/ because they
require stuff from there
* Move bridgefall.c check.c damage.c empobj.c journal.c maps.c
sectdamage.c from common/ to subs/ because they require stuff from
there
* Move cnumb.c from subs/ to common/ to satisfy common/type.o
* Move log.c fsize.c from common/ to gen/ because they really belong
there
* Move emp_config.c mapdist.c from gen/ to common/ because they really
belong there, and require stuff from libglobal.a
Also package as/ as libas.a to satisfy common/path.o.
Remaining dependencies:
lib needs
--------------------------------------------
libas.a libglobal.a
libcommon.a libas.a libglobal.a libgen.a
libgen.a
libglobal.a
liblwp.a libgen.a
libw32.a[*] libgen.a
[*] Except for service.o, which can only be linked into the server
Link order now: liblwp.a libcommon.a libas.a libgen.a libglobal.a
libw32.a. The position of libw32.a is not quite right, but works
anyway.
The function that gave its name to this file is long gone, the file's
description is bogus, and it contains just one definition. Move that
to ../subs/border.c, and delete the file.
posix_shutdown, posix_socket, socklen_t) [_WIN32]: Move socket
related externs to sys/socket.h.
(inet_ntop) [_WIN32]: Move extern to inet.h.
(tcp_listen): Remove the !WIN32 includes and use the revised
sys/socket.h, netinet/in.h, arpa/inet.h and netdb.h.
SO_REUSEADDR code for _WIN32 from tcp_listen() to
posix_setsockopt().
[_WIN32] (posix_open): Switch to _sopen() for _sopen_s() as MinGW
does not support _sopen_s() yet.
[_WIN32] (posix_fd2socket): Fix typo.
(schedulefil): New.
(set_dirs, set_paths): Rename. Initialize schedulfil.
(read_schedule): New. Can read several updates, which will be used in
later changesets.
(update_time): Change to array. Will be used in later changesets.
(update_schedule_anchor): New.
(update_init): Initialize it.
(update_get_schedule): New.
(update_init): Call it to initialize update_time[].
(update_sched): Rewrite.
(update_forced, update_wanted): Replace.
(update_reschedule): New.
(main): Call it on SIGHUP to reload the schedule.
(update_trigger, update_force, force, player_coms): Drop force's
capability to schedule updates in the future, because it's not worth
the trouble to implement again. Deities can simply edit the schedule
file to schedule updates. Remove update_force() and
update_trigger()'s parameter.
(upda): Update for new scheduler. Take care to keep output the same
as far as possible, even though it's ugly, to avoid breaking clients.
(update_policy, adj_update, update_times, hourslop, blitz_time):
econfig keys removed.
(update_demand, UPD_DEMAND_NONE, UPD_DEMAND_SCHED, UPD_DEMAND_ASYNC)
(update_demandpolicy, UDP_NORMAL, UDP_TIMES, UDP_NORMAL, UDP_BLITZ)
(UDP_MAX, UDP_DEFAULT, UDDEM_TMCHECK, UDDEM_COMSET, UDDEM_DISABLE)
(UDDEM_MAX, UDDEM_DEFAULT): econfig key and values replaced. Users
changed. wantupd.h is now empty, remove.
(demand_check): External linkage.
(update_policy_check): Now pointless, remove.
(is_daytime_near, min_to_next_daytime, regular_update_time)
(scheduled_update_time, next_scheduled_time, updatetime)
(next_update_time, next_update_check_time): Unused, Remove.
(demand_check, demandupdatecheck): Move call of demand_update_time()
from demand_check(), which controls all demand updates, to
demandupdatecheck(), which controls only unscheduled ones. Fixes
update command not to lie about the next scheduled demand update.
(demandupdatecheck): Check updates_disabled() so that zdone no longer
claims to trigger an update when it can't.
other. Ensure headers in include/ can be included in any order
(except for econfig-spec.h, which is special). New header types.h to
help avoid inclusion cycles. Sort include directives. Remove some
superflous includes.