/* file : signal.c * date : May 9th, 2003 * version : 0.2 * * This file contains the signal handling code for * SocketMud(tm). It requires the event scheduler patch, * but besides that, it should be possible to install * this snippet into any SocketMud(tm) based product. */ #include <sys/types.h> #include <sys/wait.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <signal.h> #include "mud.h" bool sigGuard = FALSE; void crashguard(int i) { FILE *fp; ITERATOR *pIter; D_MOBILE *xMob; char buf[100]; /* if signal handling is not yet enabled, we will * set the signal handling for SIGSEGV to the default * value, and then send a SIGSEGV to the MUD (again) */ if (!sigGuard) { signal(SIGSEGV, SIG_DFL); raise(SIGSEGV); return; } /* fork the MUD, allowing one process to continue and * the other to die, creating a coredump for debugging. */ if (fork() <= 0) { signal(SIGSEGV, SIG_DFL); raise(SIGSEGV); return; } wait(NULL); /* log the attempt to do a copyover */ bug("SocketMud crashed, attempting to do a copyover."); /* attempt to open the copyover file to store sockets */ if ((fp = fopen(COPYOVER_FILE, "w")) == NULL) { bug("Failed to open %s, aborting.", COPYOVER_FILE); exit(1); } /* write error message */ sprintf(buf, "\n\r <*> SocketMud Has Crashed.... <*>\n\r"); /* inform all players of the crash, and turn off compression */ pIter = AllocIterator(dmobile_list); while ((xMob = (D_MOBILE *) NextInList(pIter)) != NULL) { // for (dsock = dsock_list; dsock ; dsock = dsock_next) // { // dsock_next = dsock->next; compressEnd(xMob->socket, xMob->socket->compressing, FALSE); /* if (xMob->socket->state != STATE_PLAYING) { text_to_socket(dMob->socket, "\n\rSorry, we are rebooting. Come back in a few minutes.\n\r"); close_socket(dsock, FALSE); }*/ fprintf(fp, "%d %s %s\n", xMob->socket->control, xMob->name, xMob->socket->hostname); save_player(xMob->socket->player); text_to_socket(xMob->socket, buf); } /* close copyover file */ fprintf (fp, "-1\n"); fclose (fp); /* recycle sockets */ recycle_sockets(); /* attempt to execute SocketMud again */ sprintf(buf, "%d", control); execl(EXE_FILE, "SocketMud", "crashguard", buf, (char *) NULL, (char *) NULL); /* log failed attempt */ bug("Attempt to restore MUD failed."); exit(1); } void termguard(int i) { ITERATOR *pIter; // D_SOCKET *dsock; char buf[200]; bug("The server is shutting down, attempting to close MUD."); sprintf(buf, "\n\rServer Reboot - Stand By!!\n\r"); pIter = AllocIterator(dmobile_list); /* inform all players and save them */ /* for (dsock = dmobile_list; dsock; dsock = dsock->next) { text_to_socket(dsock, buf); if (dsock->state == STATE_PLAYING && dsock->player) save_player(dsock->player); }*/ /* close MUD */ exit(1); } bool event_game_sigguard(EVENT_DATA *event) { sigGuard = TRUE; return FALSE; } void init_sigguard() { EVENT_DATA *event; /* set the handlers for SIGSEGV (crash) * and SIGTERM (unexpected shutdown) */ signal(SIGSEGV, crashguard); signal(SIGTERM, termguard); /* enqueue the event that will enable * the signal guard. We delay this by * 10 seconds to prevent spam-copyover. */ event = alloc_event(); event->fun = &event_game_sigguard; event->type = EVENT_GAME_SIGGUARD; add_event_game(event, 10 * PULSES_PER_SECOND); }