diff --git a/include/misc.h b/include/misc.h index 6169d1bf..2bf4c082 100644 --- a/include/misc.h +++ b/include/misc.h @@ -69,7 +69,12 @@ #define hours(x) (60*60*(x)) #define days(x) (60*60*24*(x)) -extern int debug; +enum oops_action { + OOPS_ABORT, + OOPS_CRASH_DUMP, + OOPS_NOTHING +}; +extern enum oops_action oops_action; /* * If EXPR is true, an internal error occured. diff --git a/man/emp_server.6 b/man/emp_server.6 index d7b387b9..ef4c1c77 100644 --- a/man/emp_server.6 +++ b/man/emp_server.6 @@ -13,7 +13,10 @@ emp_server \- Empire server .BI \-e " configfile" ] [ -.BI \-R " random-seed" +.BI \-E " action" +] +[ +.BI \-R " seed" ] .if \nw \{\ .br @@ -42,14 +45,20 @@ pages within the game. .TP .B \-d Debug mode. This will prevent the server from forking itself into the -background. It will also make it abort when it detects an internal -error. You normally want to use this flag if you are running +background. Implies -E abort. You normally want to use this flag if +you are running .B emp_server from within a debugger. .TP .BI \-e " configfile" Use game configuration in \fIconfigfile\fR. .TP +.BI \-E " action" +What to do on recoverable internal error ("oops"): \fBabort\fP, +\fBcrash\-dump\fP (but continue), \fBnothing\fP (default). +.ie \nw \fBcrash-dump\fP is not implemented for Windows. +.el \fBcrash-dump\fP works by aborting a fork of the server process. +.TP .B \-h Help. Print brief usage information and exit. .if \nw \{\ @@ -73,7 +82,7 @@ Uninstall the Windows Service with the specified name.\} .B \-s Enable thread stack checking. .TP -.B \-R " random-seed" +.B \-R " seed" Set the seed for random function. .TP .B \-v diff --git a/src/lib/gen/log.c b/src/lib/gen/log.c index 80799b79..6cdca129 100644 --- a/src/lib/gen/log.c +++ b/src/lib/gen/log.c @@ -46,8 +46,7 @@ #include "player.h" #include "prototypes.h" -/* Debugging? If yes call abort() on internal error. */ -int debug = 1; +enum oops_action oops_action = OOPS_ABORT; static char logfile[32]; static int logfd = -1; @@ -133,7 +132,18 @@ int oops(char *msg, char *file, int line) { logerror("Oops: %s in %s:%d", msg ? msg : "bug", file, line); - if (debug) abort(); + switch (oops_action) { + case OOPS_ABORT: + abort(); + case OOPS_CRASH_DUMP: +#ifndef _WIN32 + if (fork() == 0) + abort(); +#endif + /* fall through */ + case OOPS_NOTHING: + break; + } return 1; } diff --git a/src/server/main.c b/src/server/main.c index 1a794af8..34409820 100644 --- a/src/server/main.c +++ b/src/server/main.c @@ -54,6 +54,7 @@ #include "file.h" #include "journal.h" #include "land.h" +#include "match.h" #include "misc.h" #include "nat.h" #include "nuke.h" @@ -92,13 +93,22 @@ static char pidfname[] = "server.pid"; /* Run as daemon? If yes, detach from controlling terminal etc. */ static int daemonize = 1; +static void +help(char *program_name, char *complaint) +{ + if (complaint) + fprintf(stderr, "%s: %s\n", program_name, complaint); + fprintf(stderr, "Try -h for help.\n"); +} + static void print_usage(char *program_name) { printf("Usage: %s [OPTION]...\n" - " -d debug mode\n" + " -d debug mode, implies -E abort\n" " -e CONFIG-FILE configuration file\n" " (default %s)\n" + " -E ACTION what to do on oops: abort, crash-dump, nothing (default)\n" " -h display this help and exit\n" #ifdef _WIN32 " -i install service `%s'\n" @@ -122,6 +132,7 @@ print_usage(char *program_name) int main(int argc, char **argv) { + static char *oops_key[] = { "abort", "crash-dump", "nothing", NULL }; int flags = 0; #if defined(_WIN32) int install_service_set = 0; @@ -130,28 +141,36 @@ main(int argc, char **argv) int remove_service_set = 0; #endif char *config_file = NULL; - int op, sig; + int op, idx, sig; unsigned seed = time(NULL); - debug = 0; + oops_action = OOPS_NOTHING; #ifdef _WIN32 # define XOPTS "iI:uU:" #else # define XOPTS #endif - while ((op = getopt(argc, argv, "de:hpsR:v" XOPTS)) != EOF) { + while ((op = getopt(argc, argv, "de:E:hpsR:v" XOPTS)) != EOF) { switch (op) { case 'p': flags |= EMPTH_PRINT; /* fall through */ case 'd': - debug = 1; + oops_action = OOPS_ABORT; daemonize = 0; break; case 'e': config_file = optarg; break; + case 'E': + idx = stmtch(optarg, oops_key, 0, sizeof(*oops_key)); + if (idx < 0) { + help(argv[0], "invalid argument for -E"); + return EXIT_FAILURE; + } + oops_action = idx; + break; #if defined(_WIN32) case 'I': service_name = optarg; @@ -179,19 +198,19 @@ main(int argc, char **argv) print_usage(argv[0]); return EXIT_SUCCESS; default: - fprintf(stderr, "Try -h for help.\n"); + help(argv[0], NULL); return EXIT_FAILURE; } } #if defined(_WIN32) - if ((debug || flags || config_file != NULL) && + if ((!daemonize || flags || config_file != NULL) && remove_service_set) { fprintf(stderr, "Can't use -p, -s, -d or -e with either " "-u or -U options\n"); exit(EXIT_FAILURE); } - if ((debug || flags) && install_service_set) { + if ((!daemonize || flags) && install_service_set) { fprintf(stderr, "Can't use -d, -p or -s with either " "-i or -I options\n"); exit(EXIT_FAILURE);