/* This is a watchdog pgrogram from Christian Stieber. It is not an * officially supported piece of crossfire (I hope it works, but I am not * going to be spending time debugging problems in this piece of code). The * idea is that it periodically sends/gets udp messages to the server - if * the server isn't responding, it kills it off and starts a new one. There * is a bit more logic to it - From Christian: The wrapper is just a hack. I'm using it on a Solaris machine, and it seems to work fine. Notable features: - uses the watchdog interface - if the server crashes more than 10 times, with the time between successive crashes being less than 30 seconds, the wrapper terminates itself (to prevent bringing down the machine in case of startup problems) - the server runs at nice 10 * Note that the main advantage the watchdog has over just the simple * crossloop scripts is in the case of infinite loops. For simple crashes, * the crossloop programs do a fine job. */ /* * Version 1 */ /************************************************************************/ /* * Configuration options */ /* server executable */ #define CROSSFIRE_SERVER "/usr/stud/stieber/bin/server" /* directory to cd to before starting the server */ #define CROSSFIRE_TMPDIR "/usr/stud/stieber/crossfire/tmp/" /* if the server crashes more than CRASH_COUNT times, with less than * CRASH_INTERVAL seconds between two successive crashes, the loop * program is terminated. */ #define CRASH_COUNT 10 #define CRASH_INTERVAL 30 #define USE_WATCHDOG #define ERROR_SLEEP 30 /************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include /************************************************************************/ #ifdef USE_WATCHDOG int Pipe[2]; #endif /************************************************************************/ void SignalHandler(int Unused) { if (write(Pipe[1],"",1)!=1) { perror("Pipe"); exit(EXIT_FAILURE); } } /************************************************************************/ int main(void) { int CrashCount; #ifdef USE_WATCHDOG struct protoent *protoent; struct sockaddr_in insock; int fd; memset(&insock,0,sizeof(insock)); if ((protoent=getprotobyname("udp"))==NULL) { perror("Can't get protobyname"); return EXIT_FAILURE; } if ((fd=socket(PF_INET, SOCK_DGRAM, protoent->p_proto))==-1) { perror("Can't create socket"); return EXIT_FAILURE; } insock.sin_family=AF_INET; insock.sin_port=htons((unsigned short)13325); if (bind(fd,(struct sockaddr *)&insock,sizeof(insock))==-1) { perror("Error on bind"); return EXIT_FAILURE; } #endif CrashCount=0; nice(10-nice(0)); while (CrashCountPipe[0]) { Max=fd+1; } else { Max=Pipe[0]+1; } while (select(Max,&Files,NULL,NULL,&Timeout)==-1) { if (errno!=EINTR) { perror("Error on select"); return EXIT_FAILURE; } } if (FD_ISSET(Pipe[0],&Files)) { /* crash */ unlink("core"); waitpid(Server,NULL,0); printf("Server crash!\n"); break; } else if (FD_ISSET(fd,&Files)) { /* watchdog */ char t; recv(fd,&t,1,0); } else { /* timeout */ printf("Watchdog timeout!\n"); if (kill(Server,SIGKILL)!=0) { perror("Error on kill"); return EXIT_FAILURE; } } } #else waitpid(Server,NULL,0); #endif #ifdef USE_WATCHDOG signal(SIGCHLD,OldHandler); #endif time(&EndTime); if (EndTime-StartTime