diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index c27eca06..603e0019 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -4002,7 +4002,10 @@ ftenet_generic_connection_t *FTENET_Datagram_EstablishConnection(ftenet_connecti { SockadrToNetadr(&qs, temp, &adr); NET_AdrToString(addrstr, sizeof(addrstr), &adr); - Con_Printf(CON_ERROR "Unable to bind to port %i, bound to %s instead\n", port, addrstr); + if (SSV_IsSubServer()) + Con_DLPrintf(2, CON_ERROR "Unable to bind to port %i, bound to %s instead\n", port, addrstr); + else + Con_Printf(CON_ERROR "Unable to bind to port %i, bound to %s instead\n", port, addrstr); } break; } @@ -8422,6 +8425,7 @@ void IPX_CloseSocket (int socket) #ifdef HAVE_EPOLL static qboolean stdin_ready; +static qboolean stdin_epolling; static void StdIn_Now_Ready (struct epollctx_s *ctx, unsigned int events) { stdin_ready = true; @@ -8430,13 +8434,14 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket) { int waitms; struct epoll_event waitevents[256]; - static int stdinadded = false; int n, i; - if (stdinadded != stdinissocket) + if (epoll_fd < 0) + return false; // o.O + if (stdin_epolling != stdinissocket) { static epollctx_t stdinctx = {StdIn_Now_Ready}; struct epoll_event event = {EPOLLIN, {&stdinctx}}; - stdinadded = stdinissocket; + stdin_epolling = stdinissocket; if (stdinissocket) epoll_ctl(epoll_fd, EPOLL_CTL_ADD, STDIN_FILENO, &event); else @@ -8453,7 +8458,7 @@ qboolean NET_Sleep(float seconds, qboolean stdinissocket) case EINTR: break; default: - Con_Printf("EPoll error: %i\n", err); + Con_Printf("EPoll error: %s\n", strerror(err)); break; } } @@ -8983,6 +8988,12 @@ void NET_CloseServer(void) void NET_InitServer(void) { qboolean singleplayer = (sv.allocated_client_slots == 1) && !isDedicated; + +#ifdef HAVE_EPOLL + if (epoll_fd < 0) + epoll_fd = epoll_create1(EPOLL_CLOEXEC); +#endif + if ((sv_listen_nq.value || sv_listen_dp.value || sv_listen_qw.value #ifdef QWOVERQ3 || sv_listen_q3.ival @@ -9068,6 +9079,7 @@ void NET_Shutdown (void) #ifdef HAVE_EPOLL close(epoll_fd); epoll_fd = -1; + stdin_epolling = false; #endif diff --git a/engine/common/sys_linux_threads.c b/engine/common/sys_linux_threads.c index 7b32f60e..ad1f9ffc 100644 --- a/engine/common/sys_linux_threads.c +++ b/engine/common/sys_linux_threads.c @@ -339,11 +339,12 @@ static qboolean QDECL Sys_MSV_Close (struct vfsfile_s *file) #ifdef SQL #include "sv_sql.h" #endif +#include "netinc.h" vfsfile_t *Sys_ForkServer(void) { #ifdef SERVERONLY -// extern jmp_buf host_abort; + extern jmp_buf sys_sv_serverforked; int toslave[2]; int tomaster[2]; @@ -377,17 +378,15 @@ vfsfile_t *Sys_ForkServer(void) close(toslave[0]); dup2(tomaster[1], STDOUT_FILENO); - isClusterSlave = true; + SSV_SetupControlPipe(Sys_GetStdInOutStream()); FS_UnloadPackFiles(); //these handles got wiped. make sure they're all properly wiped before loading new handles. - NET_Shutdown(); - + NET_Shutdown(); //make sure we close any of the parent's network fds ... FS_ReloadPackFiles(); - return NULL; //lets hope the caller can cope. //jump out into the main work loop -// longjmp(host_abort, 1); -// exit(0); //err... + longjmp(sys_sv_serverforked, 1); + exit(0); //err... } else { //this is the parent diff --git a/engine/server/sv_cluster.c b/engine/server/sv_cluster.c index 8f7459a8..5c4b17d7 100644 --- a/engine/server/sv_cluster.c +++ b/engine/server/sv_cluster.c @@ -40,6 +40,8 @@ #include "sv_sql.h" #endif +#define S_COLOR_SUBSERVER S_COLOR_MAGENTA + typedef struct pubsubserver_s { vfsfile_t *stream; @@ -610,7 +612,7 @@ void MSV_Status(void) clusterplayer_t *pl; for (s = subservers; s; s = s->next) { - Con_Printf("^[%i: %s\\ssv\\%u^]", s->id, s->name, s->id); + Con_Printf("^["S_COLOR_SUBSERVER"%i: %s\\ssv\\%u^]", s->id, s->name, s->id); if (s->addrv4.type != NA_INVALID) Con_Printf(" %s", NET_AdrToString(bufmem, sizeof(bufmem), &s->addrv4)); if (s->addrv6.type != NA_INVALID) @@ -850,12 +852,12 @@ static void MSV_PrintFromSubServer(pubsubserver_t *s, const char *newtext) while((nl = strchr(s->printtext, '\n'))) { //FIXME: handle overflows. *nl++ = 0; - Con_Printf("^[^6%i(%s)\\ssv\\%u^]: %s\n", s->id, s->name, s->id, s->printtext); + Con_Printf("^["S_COLOR_SUBSERVER"%i(%s)\\ssv\\%u^]: %s\n", s->id, s->name, s->id, s->printtext); memmove(s->printtext, nl, strlen(nl)+1); } if (strlen(s->printtext) > sizeof(s->printtext)/2) { - Con_Printf("^[^6%i(%s)\\ssv\\%u^]: %s\n", s->id, s->name, s->id, s->printtext); + Con_Printf("^["S_COLOR_SUBSERVER"%i(%s)\\ssv\\%u^]: %s\n", s->id, s->name, s->id, s->printtext); *s->printtext = 0; } } @@ -1123,9 +1125,9 @@ void MSV_ReadFromSubServer(pubsubserver_t *s) } MSV_SubConsole_Update(s); if (s->started) - Con_DPrintf("^[^6[%i:%s: map changed]\\ssv\\%u\\tip\\Click for server's console^]\n", s->id, s->name, s->id); + Con_DPrintf("^["S_COLOR_SUBSERVER"[%i:%s: map changed]\\ssv\\%u\\tip\\Click for server's console^]\n", s->id, s->name, s->id); else - Con_Printf("^[^6[%i:%s: new node initialised]\\ssv\\%u\\tip\\Click for server's console^]\n", s->id, s->name, s->id); + Con_Printf("^["S_COLOR_SUBSERVER"[%i:%s: new node initialised]\\ssv\\%u\\tip\\Click for server's console^]\n", s->id, s->name, s->id); s->started = true; } break; diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 539621a7..b579f0bb 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -2692,9 +2692,11 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info) if (newcl) { //client is reprising a loaded slot. - SV_BroadcastTPrintf(PRINT_HIGH, "%s reprises %s\n", name, newcl->name); if (cl->istobeloaded) + { + SV_BroadcastTPrintf(PRINT_HIGH, "%s reprises %s\n", name, newcl->name); Con_DPrintf("%s:Using loadzombie\n", svs.name); + } else Con_DPrintf("%s:Using parmzombie\n", svs.name); preserveparms = true; @@ -3088,14 +3090,14 @@ void SV_DoDirectConnect(svconnectinfo_t *fte_restrict info) SV_AcceptMessage (newcl); newcl->state = cs_free; - if (ISNQCLIENT(newcl)) + if (redirect || preserveparms) + { + } + else if (ISNQCLIENT(newcl)) { //FIXME: we should delay this until we actually have a name, because right now they'll be called unnamed or unconnected or something SV_BroadcastPrintf(PRINT_LOW, "New client connected\n"); } - else if (redirect) - { - } else if (newcl->spectator) { SV_BroadcastTPrintf(PRINT_LOW, "spectator %s connected\n", newcl->name); diff --git a/engine/server/sv_sys_unix.c b/engine/server/sv_sys_unix.c index cefadb19..c6fcf014 100644 --- a/engine/server/sv_sys_unix.c +++ b/engine/server/sv_sys_unix.c @@ -68,6 +68,10 @@ static qboolean noconinput = false; static struct termios orig, changes; +#ifdef SUBSERVERS +jmp_buf sys_sv_serverforked; +#endif + /* =============================================================================== @@ -1083,6 +1087,11 @@ int main(int argc, char *argv[]) // run one frame immediately for first heartbeat maxsleep = SV_Frame(); +#ifdef SUBSERVERS + if (setjmp(sys_sv_serverforked)) + noconinput = true; +#endif + // // main loop //