static inline int Server_accept(int listen_fd) { int cfd = -1; int rport = -1; char remote[IPADDR_SIZE]; int rc = 0; Connection *conn = NULL; cfd = netaccept(listen_fd, remote, &rport); check(cfd >= 0, "Failed to accept on listening socket."); Server *srv = Server_queue_latest(); check(srv != NULL, "Failed to get a server from the configured queue."); conn = Connection_create(srv, cfd, rport, remote); check(conn != NULL, "Failed to create connection after accept."); rc = Connection_accept(conn); check(rc == 0, "Failed to register connection, overloaded."); return 0; error: if(conn != NULL) Connection_destroy(conn); return -1; }
int Server_run() { int rc = 0; Server *srv = Server_queue_latest(); check(srv != NULL, "Failed to get a server from the configured queue."); int listen_fd = srv->listen_fd; taskname("SERVER"); while(RUNNING) { rc = Server_accept(listen_fd); if(rc == -1 && RUNNING) { log_err("Server accept failed, attempting to clear out dead weight: %d", RUNNING); int cleared = Register_cleanout(); if(cleared == 0) { taskdelay(1000); } } } return 0; error: return -1; }
int connection_route_request(Connection *conn) { Host *host = NULL; Route *route = NULL; bstring path = Request_path(conn->req); check_debug(path != NULL, "No path given, in request, ignoring."); Server *server = Server_queue_latest(); check(server != NULL, "No server in the server queue, tell Zed."); if(conn->req->host_name) { host = Server_match_backend(server, conn->req->host_name); } else { host = server->default_host; } error_unless(host, conn, 404, "Request for a host we don't have registered: %s", bdata(conn->req->host_name)); Backend *found = Host_match_backend(host, path, &route); error_unless(found, conn, 404, "Handler not found: %s", bdata(path)); Request_set_action(conn->req, found); conn->req->target_host = host; conn->req->pattern = route->pattern; conn->req->prefix = route->prefix; return Connection_backend_event(found, conn); error: return CLOSE; }
void terminate(int s) { MURDER = s == SIGTERM; switch(s) { case SIGHUP: if(!RELOAD) { RELOAD = 1; if(RELOAD_TASK) { tasksignal(RELOAD_TASK, s); } } break; default: if(!RUNNING) { log_info("SIGINT CAUGHT AGAIN, ASSUMING MURDER."); MURDER = 1; } else { RUNNING = 0; log_info("SHUTDOWN REQUESTED: %s", MURDER ? "MURDER" : "GRACEFUL (SIGINT again to EXIT NOW)"); Server *srv = Server_queue_latest(); if(srv != NULL) { fdclose(srv->listen_fd); } } break; } }
void reload_task(void *data) { RELOAD_TASK = taskself(); struct ServerTask *srv = data; while(1) { taskswitch(); task_clear_signal(); if(RELOAD) { log_info("Reload requested, will load %s from %s", bdata(srv->db_file), bdata(srv->server_id)); Server *old_srv = Server_queue_latest(); Server *new_srv = reload_server(old_srv, bdata(srv->db_file), bdata(srv->server_id)); check(new_srv, "Failed to load the new configuration, exiting."); // for this to work handlers need to die more gracefully Server_queue_push(new_srv); } else { log_info("Shutdown requested, goodbye."); break; } } taskexit(0); error: taskexit(1); }
void final_setup() { start_terminator(); Server_init(); bstring end_point = bfromcstr("inproc://access_log"); Server *srv = Server_queue_latest(); Log_init(bstrcpy(srv->access_log), end_point); Control_port_start(); taskdelay(500); log_info("-- " VERSION " Running. Copyright (C) Zed A. Shaw. Licensed BSD."); }
void taskmain(int argc, char **argv) { L = luaL_newstate(); dbg_set_log(stderr); int rc = 0; check(argc == 3, "usage: mongrel2 config.lua server_name"); //if(argc == 4) { // log_info("Using configuration module %s to load configs.", argv[3]); // rc = Config_module_load(argv[3]); // check(rc != -1, "Failed to load the config module: %s", argv[3]); //} Server_queue_init(); Server *srv = load_server(L, argv[1], argv[2], NULL); check(srv != NULL, "Aborting since can't load server."); Server_queue_push(srv); SuperPoll_get_max_fd(); // rc = clear_pid_file(srv); // check(rc == 0, "PID file failure, aborting rather than trying to start."); // rc = attempt_chroot_drop(srv); // check(rc == 0, "Major failure in chroot/droppriv, aborting."); final_setup(); taskcreate(tickertask, NULL, TICKER_TASK_STACK); struct ServerTask *srv_data = calloc(1, sizeof(struct ServerTask)); srv_data->db_file = bfromcstr(argv[1]); srv_data->server_id = bfromcstr(argv[2]); // taskcreate(reload_task, srv_data, RELOAD_TASK_STACK); rc = Server_run(); check(rc != -1, "Server had a failure and exited early."); log_info("Server run exited, goodbye."); srv = Server_queue_latest(); complete_shutdown(srv); return; error: log_err("Exiting due to error."); taskexitall(1); }