/* * Named "fork_and_dump()" mostly for historical reasons... */ void fork_and_dump(void) { epoch++; #ifndef DISKBASE if (global_dumper_pid != 0) { wall_wizards("## Dump already in progress. Skipping redundant scheduled dump."); return; } #endif last_monolithic_time = time(NULL); log_status("CHECKPOINTING: %s.#%d#", dumpfile, epoch); if (tp_dbdump_warning) wall_and_flush(tp_dumping_mesg); #ifdef DISKBASE dump_database_internal(); #else # ifndef WIN32 if ((global_dumper_pid=fork())==0) { /* We are the child. */ forked_dump_process_flag = 1; # ifdef NICEVAL /* Requested by snout of SPR, reduce the priority of the * dumper child. */ nice(NICEVAL); # endif /* NICEVAL */ set_dumper_signals(); dump_database_internal(); _exit(0); } if (global_dumper_pid < 0) { global_dumper_pid = 0; wall_wizards("## Could not fork for database dumping. Possibly out of memory."); wall_wizards("## Please restart the server when next convenient."); } # else /* !WIN32 */ dump_database_internal(); /* TODO: This is not thread safe - disabled for now... */ /*global_dumper_pid = (long) _beginthread(fork_dump_thread, 0, 0); if (global_dumper_pid == -1L) { wall_wizards("## Could not create thread for database dumping"); }*/ # endif #endif }
void dump_database(void) { epoch++; log_status("DUMPING: %s.#%d#", dumpfile, epoch); dump_database_internal(); log_status("DUMPING: %s.#%d# (done)", dumpfile, epoch); }
/* * Named "fork_and_dump()" mostly for historical reasons... */ void fork_and_dump(void) { epoch++; last_monolithic_time = time(NULL); log_status("DUMP: %s.#%d#\n", dumpfile, epoch); dump_database_internal(); host_save(); }
void boot_slave( void ) { int sv[2]; int i; int maxfds; char *s; #ifdef HAVE_GETDTABLESIZE maxfds = getdtablesize(); #else maxfds = sysconf( _SC_OPEN_MAX ); #endif if( slave_socket != -1 ) { close( slave_socket ); slave_socket = -1; } if( socketpair( AF_UNIX, SOCK_DGRAM, 0, sv ) < 0 ) { return; } /* * set to nonblocking */ #ifdef FNDELAY if( fcntl( sv[0], F_SETFL, FNDELAY ) == -1 ) { #else if( fcntl( sv[0], F_SETFL, O_NDELAY ) == -1 ) { #endif close( sv[0] ); close( sv[1] ); return; } slave_pid = vfork(); switch( slave_pid ) { case -1: close( sv[0] ); close( sv[1] ); return; case 0: /* child */ close( sv[0] ); if( dup2( sv[1], 0 ) == -1 ) { _exit( 1 ); } if( dup2( sv[1], 1 ) == -1 ) { _exit( 1 ); } for( i = 3; i < maxfds; ++i ) { close( i ); } s = ( char * ) XMALLOC( MBUF_SIZE, "boot_slave" ); sprintf( s, "%s/slave", mudconf.binhome ); execlp( s, "slave", NULL ); XFREE( s, "boot_slave" ); _exit( 1 ); } close( sv[1] ); #ifdef FNDELAY if( fcntl( sv[0], F_SETFL, FNDELAY ) == -1 ) { #else if( fcntl( sv[0], F_SETFL, O_NDELAY ) == -1 ) { #endif close( sv[0] ); return; } slave_socket = sv[0]; log_write( LOG_ALWAYS, "NET", "SLAVE", "DNS lookup slave started on fd %d", slave_socket ); } int make_socket( int port ) { int s, opt; struct sockaddr_in server; s = socket( AF_INET, SOCK_STREAM, 0 ); if( s < 0 ) { log_perror( "NET", "FAIL", NULL, "creating master socket" ); exit( 3 ); } opt = 1; if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, ( char * ) &opt, sizeof( opt ) ) < 0 ) { log_perror( "NET", "FAIL", NULL, "setsockopt" ); } server.sin_family = AF_INET; server.sin_addr.s_addr = INADDR_ANY; server.sin_port = ( unsigned short ) htons( ( unsigned short ) port ); if( !mudstate.restarting ) if( bind( s, ( struct sockaddr * ) &server, sizeof( server ) ) ) { log_perror( "NET", "FAIL", NULL, "bind" ); close( s ); exit( 4 ); } listen( s, 5 ); return s; } void shovechars( int port ) { fd_set input_set, output_set; struct timeval last_slice, current_time, next_slice, timeout, slice_timeout; int found, check; DESC *d, *dnext, *newd; int avail_descriptors, maxfds; struct stat fstatbuf; #define CheckInput(x) FD_ISSET(x, &input_set) #define CheckOutput(x) FD_ISSET(x, &output_set) mudstate.debug_cmd = ( char * ) "< shovechars >"; if( !mudstate.restarting ) { sock = make_socket( port ); } if( !mudstate.restarting ) { maxd = sock + 1; } get_tod( &last_slice ); #ifdef HAVE_GETDTABLESIZE maxfds = getdtablesize(); #else maxfds = sysconf( _SC_OPEN_MAX ); #endif avail_descriptors = maxfds - 7; while( mudstate.shutdown_flag == 0 ) { get_tod( ¤t_time ); last_slice = update_quotas( last_slice, current_time ); process_commands(); if( mudstate.shutdown_flag ) { break; } /* * We've gotten a signal to dump flatfiles */ if( mudstate.flatfile_flag && !mudstate.dumping ) { if( *mudconf.dump_msg ) { raw_broadcast( 0, "%s", mudconf.dump_msg ); } mudstate.dumping = 1; log_write( LOG_DBSAVES, "DMP", "CHKPT", "Flatfiling: %s.#%d#", mudconf.db_file, mudstate.epoch ); dump_database_internal( DUMP_DB_FLATFILE ); mudstate.dumping = 0; if( *mudconf.postdump_msg ) { raw_broadcast( 0, "%s", mudconf.postdump_msg ); } mudstate.flatfile_flag = 0; } /* * test for events */ dispatch(); /* * any queued robot commands waiting? */ timeout.tv_sec = que_next(); timeout.tv_usec = 0; next_slice = msec_add( last_slice, mudconf.timeslice ); slice_timeout = timeval_sub( next_slice, current_time ); FD_ZERO( &input_set ); FD_ZERO( &output_set ); /* * Listen for new connections if there are free descriptors */ if( ndescriptors < avail_descriptors ) { FD_SET( sock, &input_set ); } /* * Listen for replies from the slave socket */ if( slave_socket != -1 ) { FD_SET( slave_socket, &input_set ); } /* * Mark sockets that we want to test for change in status */ DESC_ITER_ALL( d ) { if( !d->input_head ) { FD_SET( d->descriptor, &input_set ); } if( d->output_head ) { FD_SET( d->descriptor, &output_set ); } } /* * Wait for something to happen */ found = select( maxd, &input_set, &output_set, ( fd_set * ) NULL, &timeout ); if( found < 0 ) { if( errno == EBADF ) { /* * This one is bad, as it results in a spiral * of doom, unless we can figure out what the * bad file descriptor is and get rid of it. */ log_perror( "NET", "FAIL", "checking for activity", "select" ); DESC_ITER_ALL( d ) { if( fstat( d->descriptor, &fstatbuf ) < 0 ) { /* * It's a player. Just toss * the connection. */ log_write( LOG_PROBLEMS, "ERR", "EBADF", "Bad descriptor %d", d->descriptor ); shutdownsock( d,R_SOCKDIED ); } } if( ( slave_socket == -1 ) || ( fstat( slave_socket, &fstatbuf ) < 0 ) ) { /* * Try to restart the slave, since it * presumably died. */ log_write( LOG_PROBLEMS, "ERR", "EBADF", "Bad slave descriptor %d", slave_socket ); boot_slave(); } if( ( sock != -1 ) && ( fstat( sock, &fstatbuf ) < 0 ) ) { /* * That's it, game over. */ log_write( LOG_PROBLEMS, "ERR", "EBADF", "Bad game port descriptor %d", sock ); break; } } else if( errno != EINTR ) { log_perror( "NET", "FAIL", "checking for activity", "select" ); } continue; }