server: Respond quickly to SIGINT and stop startup if some module fails to compile

This commit is contained in:
Perttu Ahola 2014-09-24 14:10:44 +03:00
parent 4f93467716
commit abc39ba044
5 changed files with 71 additions and 19 deletions

View File

@ -40,7 +40,9 @@ namespace interface
{ {
virtual ~Server(){} virtual ~Server(){}
virtual void load_module(const ss_ &module_name, const ss_ &path) = 0; virtual void shutdown(int exit_status=0) = 0;
virtual bool load_module(const ss_ &module_name, const ss_ &path) = 0;
virtual void unload_module(const ss_ &module_name) = 0; virtual void unload_module(const ss_ &module_name) = 0;
virtual void reload_module(const ss_ &module_name, const ss_ &path) = 0; virtual void reload_module(const ss_ &module_name, const ss_ &path) = 0;
virtual ss_ get_modules_path() = 0; virtual ss_ get_modules_path() = 0;

View File

@ -112,9 +112,11 @@ int main(int argc, char *argv[])
} }
up_<server::State> state(server::createState()); up_<server::State> state(server::createState());
state->load_modules(module_path); state->load_modules(module_path);
// Main loop // Main loop
int exit_status = 0;
uint64_t next_tick_us = get_timeofday_us(); uint64_t next_tick_us = get_timeofday_us();
uint64_t t_per_tick = 1000 * 100; uint64_t t_per_tick = 1000 * 100;
set_<int> attempt_bad_fds; set_<int> attempt_bad_fds;
@ -150,6 +152,10 @@ int main(int argc, char *argv[])
int r = select(fd_max + 1, &rfds, NULL, NULL, &tv); int r = select(fd_max + 1, &rfds, NULL, NULL, &tv);
if(r == -1){ if(r == -1){
if(errno == EINTR && g_sigint_received){
// Fine, we're quitting
break;
}
// Error // Error
num_consequent_valid_selects = 0; num_consequent_valid_selects = 0;
log_w("main", "select() returned -1: %s (fds: %s)", log_w("main", "select() returned -1: %s (fds: %s)",
@ -207,8 +213,11 @@ int main(int argc, char *argv[])
} }
state->handle_events(); state->handle_events();
if(state->is_shutdown_requested(&exit_status))
break;
} }
return 0; return exit_status;
} }

View File

@ -20,6 +20,7 @@
using interface::Event; using interface::Event;
extern server::Config g_server_config; extern server::Config g_server_config;
extern bool g_sigint_received;
namespace server { namespace server {
@ -104,6 +105,9 @@ struct CState: public State, public interface::Server
Event::Type event_type; Event::Type event_type;
}; };
bool m_shutdown_requested = false;
int m_shutdown_exit_status = 0;
up_<rccpp::Compiler> m_compiler; up_<rccpp::Compiler> m_compiler;
ss_ m_modules_path; ss_ m_modules_path;
@ -146,7 +150,25 @@ struct CState: public State, public interface::Server
} }
} }
void load_module(const ss_ &module_name, const ss_ &path) void shutdown(int exit_status)
{
if(m_shutdown_requested && exit_status == 0){
// Only reset these values for exit values indicating failure
return;
}
log_i(MODULE, "Server shutdown requested; exit_status=%i", exit_status);
m_shutdown_requested = true;
m_shutdown_exit_status = exit_status;
}
bool is_shutdown_requested(int *exit_status=nullptr)
{
if(m_shutdown_requested && exit_status)
*exit_status = m_shutdown_exit_status;
return m_shutdown_requested;
}
bool load_module(const ss_ &module_name, const ss_ &path)
{ {
interface::MutexScope ms(m_modules_mutex); interface::MutexScope ms(m_modules_mutex);
@ -162,7 +184,7 @@ struct CState: public State, public interface::Server
sv_<ss_> include_dirs = m_compiler->include_directories; sv_<ss_> include_dirs = m_compiler->include_directories;
include_dirs.push_back(m_modules_path); include_dirs.push_back(m_modules_path);
sv_<ss_> includes = list_includes(init_cpp_path, include_dirs); sv_<ss_> includes = list_includes(init_cpp_path, include_dirs);
log_i(MODULE, "Includes: %s", cs(dump(includes))); log_v(MODULE, "Includes: %s", cs(dump(includes)));
files_to_watch.insert(files_to_watch.end(), includes.begin(), includes.end()); files_to_watch.insert(files_to_watch.end(), includes.begin(), includes.end());
if(m_module_file_watches.count(module_name) == 0){ if(m_module_file_watches.count(module_name) == 0){
@ -189,8 +211,8 @@ struct CState: public State, public interface::Server
if(dep.type == "ldflags") if(dep.type == "ldflags")
extra_ldflags += dep.value+" "; extra_ldflags += dep.value+" ";
} }
log_i(MODULE, "extra_cxxflags: %s", cs(extra_cxxflags)); log_v(MODULE, "extra_cxxflags: %s", cs(extra_cxxflags));
log_i(MODULE, "extra_ldflags: %s", cs(extra_ldflags)); log_v(MODULE, "extra_ldflags: %s", cs(extra_ldflags));
m_compiler->include_directories.push_back(m_modules_path); m_compiler->include_directories.push_back(m_modules_path);
bool build_ok = m_compiler->build(module_name, init_cpp_path, build_dst, bool build_ok = m_compiler->build(module_name, init_cpp_path, build_dst,
@ -199,7 +221,7 @@ struct CState: public State, public interface::Server
if(!build_ok){ if(!build_ok){
log_w(MODULE, "Failed to build module %s", cs(module_name)); log_w(MODULE, "Failed to build module %s", cs(module_name));
return; return false;
} }
// Construct instance // Construct instance
@ -209,7 +231,7 @@ struct CState: public State, public interface::Server
if(m == nullptr){ if(m == nullptr){
log_w(MODULE, "Failed to construct module %s instance", log_w(MODULE, "Failed to construct module %s instance",
cs(module_name)); cs(module_name));
return; return false;
} }
m_modules[module_name] = ModuleContainer(m); m_modules[module_name] = ModuleContainer(m);
m_modules[module_name].path = path; m_modules[module_name].path = path;
@ -224,6 +246,7 @@ struct CState: public State, public interface::Server
emit_event(Event("core:module_loaded", emit_event(Event("core:module_loaded",
new interface::ModuleLoadedEvent(module_name))); new interface::ModuleLoadedEvent(module_name)));
return true;
} }
void load_modules(const ss_ &path) void load_modules(const ss_ &path)
@ -429,6 +452,10 @@ struct CState: public State, public interface::Server
// can be deleted while this is running, because modules are deleted // can be deleted while this is running, because modules are deleted
// only by this same thread. // only by this same thread.
for(size_t loop_i = 0;; loop_i++){ for(size_t loop_i = 0;; loop_i++){
if(g_sigint_received){
// Get out fast
throw ServerShutdownRequest("Server shutdown requested via SIGINT");
}
sv_<Event> event_queue_snapshot; sv_<Event> event_queue_snapshot;
sv_<sv_<ModuleContainer*>> event_subs_snapshot; sv_<sv_<ModuleContainer*>> event_subs_snapshot;
{ {

View File

@ -11,6 +11,11 @@ namespace interface
namespace server namespace server
{ {
struct ServerShutdownRequest: public Exception {
ss_ msg;
ServerShutdownRequest(const ss_ &msg): Exception(msg){}
};
struct ModuleNotFoundException: public Exception { struct ModuleNotFoundException: public Exception {
ss_ msg; ss_ msg;
ModuleNotFoundException(const ss_ &msg): Exception(msg){} ModuleNotFoundException(const ss_ &msg): Exception(msg){}
@ -19,7 +24,9 @@ namespace server
struct State struct State
{ {
virtual ~State(){} virtual ~State(){}
virtual void load_module(const ss_ &module_name, const ss_ &path) = 0; virtual void shutdown(int exit_status=0) = 0;
virtual bool is_shutdown_requested(int *exit_status=nullptr) = 0;
virtual bool load_module(const ss_ &module_name, const ss_ &path) = 0;
virtual void load_modules(const ss_ &path) = 0; virtual void load_modules(const ss_ &path) = 0;
virtual interface::Module* get_module(const ss_ &module_name) = 0; virtual interface::Module* get_module(const ss_ &module_name) = 0;
virtual interface::Module* check_module(const ss_ &module_name) = 0; virtual interface::Module* check_module(const ss_ &module_name) = 0;

View File

@ -41,18 +41,25 @@ struct Module: public interface::Module
void on_load_modules() void on_load_modules()
{ {
ss_ builtin = m_server->get_builtin_modules_path(); ss_ builtin = m_server->get_builtin_modules_path();
m_server->load_module("network", builtin+"/network"); ss_ current = m_server->get_modules_path();
m_server->load_module("client_file", builtin+"/client_file");
m_server->load_module("client_lua", builtin+"/client_lua");
m_server->load_module("client_data", builtin+"/client_data");
sv_<ss_> load_list = { sv_<std::pair<ss_, ss_>> load_list = {
"test1", {builtin, "network"},
//"test2", {builtin, "client_file"},
//"minigame", {builtin, "client_lua"},
{builtin, "client_data"},
{current, "test1"},
//{current, "test2"},
//{current, "minigame"},
}; };
for(const ss_ &name : load_list){ for(auto &pair : load_list){
m_server->load_module(name, m_server->get_modules_path()+"/"+name); const ss_ &name = pair.second;
const ss_ &path = pair.first+"/"+pair.second;
bool ok = m_server->load_module(name, path);
if(!ok){
m_server->shutdown(1);
break;
}
} }
/*// TODO: Dependencies /*// TODO: Dependencies