/* when we catch a signal and want to exit we call this function to do it gracefully */ static void mk_signal_exit() { int i; uint64_t val; /* ignore future signals to properly handle the cleanup */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); /* Distribute worker signals to stop working */ val = MK_SCHEDULER_SIGNAL_FREE_ALL; for (i = 0; i < config->workers; i++) { write(sched_list[i].signal_channel, &val, sizeof(val)); } /* Wait for workers to finish */ for (i = 0; i < config->workers; i++) { pthread_join(sched_list[i].tid, NULL); } mk_utils_remove_pid(); mk_plugin_exit_all(); mk_config_free_all(); mk_mem_free(sched_list); mk_clock_exit(); mk_info("Exiting... >:("); exit(EXIT_SUCCESS); }
/* Run current process in background mode (daemon, evil Monkey >:) */ int mk_utils_set_daemon() { pid_t pid; if ((pid = fork()) < 0){ mk_err("Error: Failed creating to switch to daemon mode(fork failed)"); exit(EXIT_FAILURE); } if (pid > 0) /* parent */ exit(EXIT_SUCCESS); /* set files mask */ umask(0); /* Create new session */ setsid(); if (chdir("/") < 0) { /* make sure we can unmount the inherited filesystem */ mk_err("Error: Unable to unmount the inherited filesystem in the daemon process"); exit(EXIT_FAILURE); } /* Our last STDOUT messages */ mk_details(); mk_info("Background mode ON"); fclose(stderr); fclose(stdout); return 0; }
int _mkp_event_write(int fd) { struct cache_req_t *req = curr_reqs_get(fd); if (!req) { return MK_PLUGIN_RET_EVENT_NEXT; } if (req->bytes_to_send <= 0) { mk_info("no data to send, returning event_write!"); return MK_PLUGIN_RET_EVENT_CLOSE; } int ret = serve_req(req); if (ret <= 0) { curr_reqs_del(fd); mk_api->http_request_end(fd); return MK_PLUGIN_RET_EVENT_OWNED; } else { return MK_PLUGIN_RET_EVENT_CONTINUE; } }
int serve_req(struct cache_req_t *req) { if (req->file->buf.data == (void *) -1) { mk_info("mmap invalid, sending standard file"); return socket_serve_req_fd(req); } return socket_serve_req_splice(req); }
/* when we catch a signal and want to exit we call this function to do it gracefully */ static void mk_signal_exit() { /* ignore future signals to properly handle the cleanup */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); mk_exit_all(); mk_info("Exiting... >:("); _exit(EXIT_SUCCESS); }
int _mkp_core_prctx(struct server_config *conf) { mk_info("Started Monkey Cache plugin"); curr_reqs_process_init(); cache_req_process_init(); pipe_buf_process_init(); cache_file_process_init(); timer_process_init(); cache_stats_process_init(); config = conf; return 0; }
/* when we catch a signal and want to exit we call this function to do it gracefully */ static void mk_signal_exit() { /* ignore future signals to properly handle the cleanup */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); mk_user_undo_uidgid(); mk_utils_remove_pid(mk_config->path_conf_pidfile); mk_exit_all(); mk_info("Exiting... >:("); _exit(EXIT_SUCCESS); }
/* when we catch a signal and want to exit we call this function to do it gracefully */ static void mk_signal_exit() { /* ignore future signals to properly handle the cleanup */ signal(SIGTERM, SIG_IGN); signal(SIGINT, SIG_IGN); signal(SIGHUP, SIG_IGN); mk_utils_remove_pid(); mk_plugin_exit_all(); #ifdef SAFE_FREE mk_config_free_all(); #endif mk_info("Exiting... >:("); _exit(EXIT_SUCCESS); }
void mk_server_loop(int server_fd) { int ret; int remote_fd; /* Activate TCP_DEFER_ACCEPT */ if (mk_socket_set_tcp_defer_accept(server_fd) != 0) { mk_warn("TCP_DEFER_ACCEPT failed"); } /* Rename worker */ mk_utils_worker_rename("monkey: server"); mk_info("HTTP Server started"); while (1) { remote_fd = mk_socket_accept(server_fd); if (mk_unlikely(remote_fd == -1)) { continue; } #ifdef TRACE MK_TRACE("New connection arrived: FD %i", remote_fd); int i; struct sched_list_node *node; node = sched_list; for (i=0; i < config->workers; i++) { MK_TRACE("Worker Status"); MK_TRACE(" WID %i / conx = %llu", node[i].idx, node[i].accepted_connections - node[i].closed_connections); } #endif /* Assign socket to worker thread */ ret = mk_sched_add_client(remote_fd); if (ret == -1) { close(remote_fd); } } }
/* MAIN */ int main(int argc, char **argv) { int opt; int port_override = -1; int workers_override = -1; int run_daemon = 0; char *path_config = NULL; char *server_config = NULL; static const struct option long_opts[] = { { "configdir", required_argument, NULL, 'c' }, { "serverconf",required_argument, NULL, 's' }, { "build", no_argument, NULL, 'b' }, { "daemon", no_argument, NULL, 'D' }, { "port", required_argument, NULL, 'p' }, { "workers", required_argument, NULL, 'w' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { NULL, 0, NULL, 0 } }; while ((opt = getopt_long(argc, argv, "bDSvhp:w:c:s:", long_opts, NULL)) != -1) { switch (opt) { case 'b': mk_build_info(); exit(EXIT_SUCCESS); case 'v': mk_version(); exit(EXIT_SUCCESS); case 'h': mk_help(EXIT_SUCCESS); case 'D': run_daemon = 1; break; case 'p': port_override = atoi(optarg); break; case 'w': workers_override = atoi(optarg); break; case 'c': path_config = optarg; break; case 's': server_config = optarg; break; case '?': mk_help(EXIT_FAILURE); } } /* setup basic configurations */ config = mk_mem_malloc_z(sizeof(struct server_config)); /* set configuration path */ if (!path_config) { config->path_config = MONKEY_PATH_CONF; } else { config->path_config = path_config; } /* set target configuration file for the server */ if (!server_config) { config->server_config = M_DEFAULT_CONFIG_FILE; } else { config->server_config = server_config; } if (run_daemon) config->is_daemon = MK_TRUE; else config->is_daemon = MK_FALSE; #ifdef TRACE monkey_init_time = time(NULL); MK_TRACE("Monkey TRACE is enabled"); env_trace_filter = getenv("MK_TRACE_FILTER"); pthread_mutex_init(&mutex_trace, (pthread_mutexattr_t *) NULL); #endif mk_version(); mk_signal_init(); #ifdef LINUX_TRACE mk_info("Linux Trace enabled"); #endif /* Override number of thread workers */ if (workers_override >= 0) { config->workers = workers_override; } else { config->workers = -1; } /* Core and Scheduler setup */ mk_config_start_configure(); mk_sched_init(); /* Clock init that must happen before starting threads */ mk_clock_sequential_init(); /* Load plugins */ mk_plugin_init(); mk_plugin_read_config(); /* Override TCP port if it was set in the command line */ if (port_override > 0) { config->serverport = port_override; } /* Server listening socket */ config->server_fd = mk_socket_server(config->serverport, config->listen_addr); /* Running Monkey as daemon */ if (config->is_daemon == MK_TRUE) { mk_utils_set_daemon(); } /* Register PID of Monkey */ mk_utils_register_pid(); /* Workers: logger and clock */ mk_utils_worker_spawn((void *) mk_clock_worker_init, NULL); /* Init mk pointers */ mk_mem_pointers_init(); /* Init thread keys */ mk_thread_keys_init(); /* Change process owner */ mk_user_set_uidgid(); /* Configuration sanity check */ mk_config_sanity_check(); /* Print server details */ mk_details(); /* Invoke Plugin PRCTX hooks */ mk_plugin_core_process(); /* Launch monkey http workers */ mk_server_launch_workers(); /* Wait until all workers report as ready */ while (1) { int i, ready = 0; pthread_mutex_lock(&mutex_worker_init); for (i = 0; i < config->workers; i++) { if (sched_list[i].initialized) ready++; } pthread_mutex_unlock(&mutex_worker_init); if (ready == config->workers) break; usleep(10000); } /* Server loop, let's listen for incomming clients */ mk_server_loop(config->server_fd); mk_mem_free(config); return 0; }
/* MAIN */ int main(int argc, char **argv) { int opt; char *port_override = NULL; int workers_override = -1; int run_daemon = 0; int balancing_mode = MK_FALSE; int allow_shared_sockets = MK_FALSE; char *one_shot = NULL; char *pid_file = NULL; char *transport_layer = NULL; char *path_config = NULL; char *server_conf_file = NULL; char *plugin_load_conf_file = NULL; char *sites_conf_dir = NULL; char *plugins_conf_dir = NULL; char *mimes_conf_file = NULL; static const struct option long_opts[] = { { "configdir", required_argument, NULL, 'c' }, { "serverconf", required_argument, NULL, 's' }, { "build", no_argument, NULL, 'b' }, { "daemon", no_argument, NULL, 'D' }, { "pid-file", required_argument, NULL, 'I' }, { "port", required_argument, NULL, 'p' }, { "one-shot", required_argument, NULL, 'o' }, { "transport", required_argument, NULL, 't' }, { "workers", required_argument, NULL, 'w' }, { "version", no_argument, NULL, 'v' }, { "help", no_argument, NULL, 'h' }, { "mimes-conf-file", required_argument, NULL, 'm' }, { "plugin-load-conf-file", required_argument, NULL, 'l' }, { "plugins-conf-dir", required_argument, NULL, 'P' }, { "sites-conf-dir", required_argument, NULL, 'S' }, { "balancing-mode", no_argument, NULL, 'B' }, { "allow-shared-sockets", no_argument, NULL, 'T' }, { NULL, 0, NULL, 0 } }; while ((opt = getopt_long(argc, argv, "bDI:Svhp:o:t:w:c:s:m:l:P:S:BT", long_opts, NULL)) != -1) { switch (opt) { case 'b': mk_build_info(); exit(EXIT_SUCCESS); case 'v': mk_version(); exit(EXIT_SUCCESS); case 'h': mk_help(EXIT_SUCCESS); case 'D': run_daemon = 1; break; case 'I': pid_file = optarg; break; case 'p': port_override = optarg; break; case 'o': one_shot = optarg; break; case 't': transport_layer = mk_string_dup(optarg); break; case 'w': workers_override = atoi(optarg); break; case 'c': path_config = optarg; break; case 's': server_conf_file = optarg; break; case 'm': mimes_conf_file = optarg; break; case 'P': plugins_conf_dir = optarg; break; case 'S': sites_conf_dir = optarg; break; case 'B': balancing_mode = MK_TRUE; break; case 'T': allow_shared_sockets = MK_TRUE; break; case 'l': plugin_load_conf_file = optarg; break; case '?': mk_help(EXIT_FAILURE); } } /* setup basic configurations */ mk_config = mk_config_init(); /* Init Kernel version data */ mk_kernel_init(); mk_kernel_features(); /* set configuration path */ if (!path_config) { mk_config->path_config = MK_PATH_CONF; } else { mk_config->path_config = path_config; } /* set target configuration file for the server */ if (!server_conf_file) { mk_config->server_conf_file = MK_DEFAULT_CONFIG_FILE; } else { mk_config->server_conf_file = server_conf_file; } if (!pid_file) { mk_config->pid_file_path = NULL; } else { mk_config->pid_file_path = pid_file; } if (run_daemon) { mk_config->is_daemon = MK_TRUE; } else { mk_config->is_daemon = MK_FALSE; } if (!mimes_conf_file) { mk_config->mimes_conf_file = MK_DEFAULT_MIMES_CONF_FILE; } else { mk_config->mimes_conf_file = mimes_conf_file; } if (!plugin_load_conf_file) { mk_config->plugin_load_conf_file = MK_DEFAULT_PLUGIN_LOAD_CONF_FILE; } else { mk_config->plugin_load_conf_file = plugin_load_conf_file; } if (!sites_conf_dir) { mk_config->sites_conf_dir = MK_DEFAULT_SITES_CONF_DIR; } else { mk_config->sites_conf_dir = sites_conf_dir; } if (!plugins_conf_dir) { mk_config->plugins_conf_dir = MK_DEFAULT_PLUGINS_CONF_DIR; } else { mk_config->plugins_conf_dir = plugins_conf_dir; } /* Override some configuration */ mk_config->one_shot = one_shot; mk_config->port_override = port_override; mk_config->transport_layer = transport_layer; #ifdef TRACE monkey_init_time = time(NULL); MK_TRACE("Monkey TRACE is enabled"); env_trace_filter = getenv("MK_TRACE_FILTER"); pthread_mutex_init(&mutex_trace, (pthread_mutexattr_t *) NULL); #endif pthread_mutex_init(&mutex_port_init, (pthread_mutexattr_t *) NULL); mk_version(); mk_signal_init(); #ifdef LINUX_TRACE mk_info("Linux Trace enabled"); #endif /* Override number of thread workers */ if (workers_override >= 0) { mk_config->workers = workers_override; } else { mk_config->workers = -1; } /* Core and Scheduler setup */ mk_config_start_configure(); mk_sched_init(); if (balancing_mode == MK_TRUE) { mk_config->scheduler_mode = MK_SCHEDULER_FAIR_BALANCING; } /* Clock init that must happen before starting threads */ mk_clock_sequential_init(); /* Load plugins */ mk_plugin_api_init(); mk_plugin_load_all(); /* Running Monkey as daemon */ if (mk_config->is_daemon == MK_TRUE) { mk_utils_set_daemon(); } /* Register PID of Monkey */ mk_utils_register_pid(); /* Workers: logger and clock */ mk_clock_tid = mk_utils_worker_spawn((void *) mk_clock_worker_init, NULL); /* Init thread keys */ mk_thread_keys_init(); /* Configuration sanity check */ mk_config_sanity_check(); if (mk_config->scheduler_mode == MK_SCHEDULER_REUSEPORT && mk_config_listen_check_busy() == MK_TRUE && allow_shared_sockets == MK_FALSE) { mk_warn("Some Listen interface is busy, re-try using -T. Aborting."); exit(EXIT_FAILURE); } /* Invoke Plugin PRCTX hooks */ mk_plugin_core_process(); /* Launch monkey http workers */ MK_TLS_INIT(); mk_server_launch_workers(); /* Print server details */ mk_details(); /* Change process owner */ mk_user_set_uidgid(); /* Server loop, let's listen for incomming clients */ mk_server_loop(); mk_mem_free(mk_config); return 0; }