/** * @brief Main entry point * * @param argc argument counter * @param argv argument array * @details uses opts global var * * @return EXIT_SUCCESS on success, EXIT_FAILURE otherwise */ int main(int argc, char **argv) { char cmd[MAX_LINE_LENGTH]; /* chack opts */ if(parse_args(argc, argv) == -1) { usage(); return EXIT_FAILURE; } /* needs to be done here */ if(opts.opt_e) { (void) fprintf(stdout, "<html><head></head><body>\n"); } /* read commands */ while(fgets(cmd, MAX_LINE_LENGTH, stdin) != NULL) { /* and spanw the workers */ if(spawn_worker(cmd) == -1) { return EXIT_FAILURE; } } if(opts.opt_e) { (void) fprintf(stdout, "</body></head>\n"); } return EXIT_SUCCESS; }
int setup_workers(struct ev_loop* loop, struct listener_s* listener) { char* ip = listener->argv[1]; uint16_t port = (uint16_t)atoi(listener->argv[2]); int listen_fd; #ifndef SO_REUSEPORT listen_fd = start_listen(ip, port); #endif pid_t pid; int i; struct worker_s* workers = listener->workers; for (i = 0; i < listener->worker_count; i++) { #ifdef SO_REUSEPORT listen_fd = start_listen(ip, port); #endif workers[i].listen_fd = listen_fd; workers[i].worker_id = i; workers[i].listener = listener; pid = spawn_worker(&workers[i]); if (pid < 0) { return -1; } workers[i].pid = pid; ev_child_init(&workers[i].cwatcher, exit_cb, pid, 0); ev_child_start(loop, &workers[i].cwatcher); } return 0; }
int init_workers(int desired_workers) { worker_process **wps; int i; if (desired_workers <= 0) { desired_workers = 4; } if (workers_alive() == desired_workers) return 0; /* can't shrink the number of workers (yet) */ if (desired_workers < num_workers) return -1; wps = calloc(desired_workers, sizeof(worker_process *)); if (!wps) return -1; if (workers) { if (num_workers < desired_workers) { for (i = 0; i < num_workers; i++) { wps[i] = workers[i]; } } free(workers); } workers = wps; for (i = 0; i < desired_workers; i++) { int ret; worker_process *wp; if (wps[i]) continue; wp = spawn_worker(worker_init_func, (void *)get_global_macros()); if (!wp) { logit(NSLOG_RUNTIME_WARNING, TRUE, "Failed to spawn worker: %s\n", strerror(errno)); free_worker_memory(0); return ERROR; } set_socket_options(wp->sd, 256 * 1024); wps[i] = wp; ret = iobroker_register(nagios_iobs, wp->sd, wp, handle_worker_result); if (ret < 0) { printf("Failed to register worker socket with iobroker %p\n", nagios_iobs); exit(1); } } num_workers = desired_workers; logit(NSLOG_INFO_MESSAGE, TRUE, "Workers spawned: %d\n", num_workers); return 0; }
balanced_thread_pool(float idle_time_threshold_for_new_worker = .1f, float kernel_time_thershold_for_despawn_extra_worker = .1f, float idle_time_threshold_for_despawn_surplus_worker = .15f) : idle_time_threshold_for_new_worker(idle_time_threshold_for_new_worker), kernel_time_thershold_for_despawn_extra_worker(kernel_time_thershold_for_despawn_extra_worker), idle_time_threshold_for_despawn_surplus_worker(idle_time_threshold_for_despawn_surplus_worker) { const int threads = min_worker_threads(); const int max_threads = std::thread::hardware_concurrency(); for (int i = 0; i < threads; ++i) spawn_worker(max_threads - threads + i); }
void mt_task_queue::enqueue(gtask const & t) { lean_always_assert(get_state(t).load() < task_state::Running); lean_always_assert(get_imp(t)); get_state(t) = task_state::Queued; m_queue[get_prio(t)].push_back(t); if (m_required_workers > 0) { spawn_worker(); } else { m_queue_added.notify_one(); } notify_queue_changed(); }
int main(int argc, char **argv) { simple_worker *wp; int i; #ifdef HAVE_SIGACTION struct sigaction sig_action; sig_action.sa_sigaction = NULL; sigfillset(&sig_action.sa_mask); sig_action.sa_flags=SA_NOCLDSTOP; sig_action.sa_handler = child_exited; sigaction(SIGCHLD, &sig_action, NULL); sig_action.sa_flags = SA_NODEFER|SA_RESTART; sig_action.sa_handler = sighandler; sigfillset(&sig_action.sa_mask); sigaction(SIGINT, &sig_action, NULL); sigaction(SIGPIPE, &sig_action, NULL); #else /* HAVE_SIGACTION */ signal(SIGINT, sighandler); signal(SIGPIPE, sighandler); signal(SIGCHLD, child_exited); #endif /* HAVE_SIGACTION */ iobs = iobroker_create(); if (!iobs) die("Failed to create io broker set"); for (i = 0; i < NWPS; i++) { wp = spawn_worker(print_some_crap, "lalala"); if (!wp) { die("Failed to spawn worker(s)\n"); } wps[i] = wp; printf("Registering worker sd %d with io broker\n", wp->sd); iobroker_register(iobs, wp->sd, wp, print_input); } iobroker_register(iobs, fileno(stdin), NULL, send_command); /* get to work */ while (!sigreceived && iobroker_get_num_fds(iobs)) { iobroker_poll(iobs, -1); } for (i = 0; i < NWPS; i++) { kill(wps[i]->pid, SIGKILL); } return 0; }
/* * @brief Load balances the pool. * Creates/destroys workers, as needed. */ void load_balance() { assert(is_main_thread()); const auto now = std::chrono::high_resolution_clock::now(); std::chrono::duration<float> time_since_last_pool_balance = now - last_pool_balance; if (time_since_last_pool_balance.count() < .05f) return; last_pool_balance = now; float idle_frac = .0f; float kernel_frac = .0f; float user_frac = .0f; if (!sys_times.get_times_since_last_call(idle_frac, kernel_frac, user_frac)) return; // Check for dead workers (e.g. exception thrown) for (auto it = workers.begin(); it != workers.end();) { if (it->is_terminated()) it = workers.erase(it); else ++it; } // Load balance const unsigned min_threads = min_worker_threads(); const auto req = get_pending_requests_count(); const auto threads_sleeping = get_sleeping_workers_count(); const auto total_workers_count = get_workers_count(); if (threads_sleeping == 0 && idle_frac > idle_time_threshold_for_new_worker && total_workers_count < max_worker_threads()) { spawn_worker(); } else if (workers.size() > min_threads && (kernel_frac > kernel_time_thershold_for_despawn_extra_worker || (req == 0 && idle_frac > idle_time_threshold_for_despawn_surplus_worker) || threads_sleeping > 1)) { despawn_worker(); } }
void exit_cb(struct ev_loop* loop, struct ev_child* cwatcher, int status) { struct worker_s* worker = container_of(cwatcher, struct worker_s, cwatcher); ev_child_stop(loop, cwatcher); err("worker[pid:%d] exit with status:%d, stop_moniter:%d", worker->pid, cwatcher->rstatus, worker->listener->stop_moniter); struct timeval tv; gettimeofday(&tv, 0); if (worker->listener->stop_moniter || 2 > ((int)tv.tv_sec - worker->starttime)) { return; } worker->pid = spawn_worker(worker); if (-1 == worker->pid) { err("spawn worker failed, worker_id:%d", worker->worker_id); exit(EXIT_FAILURE); } err("worker %d restart, new pid: %d", worker->worker_id, worker->pid); ev_child_set(cwatcher, worker->pid, 0); ev_child_start(loop, cwatcher); }
int main(int argc, char *argv[]) { ssize_t n; Packet pckt_req; struct sigaction sigchld_action = { .sa_handler = SIG_DFL, .sa_flags = SA_NOCLDWAIT }; // Avoid having to wait for child processes to exit sigaction(SIGCHLD, &sigchld_action, NULL); printf("Starting server... "); if (init_server() == -1) { printf("\x1B[31m[ERROR]\x1B[0m\nError initializing server.\n"); return 1; } printf("\x1B[32m[OK]\x1B[0m\n"); // Assign custom sleep time or default if error or no time specified if (argc == 2 && sscanf(argv[1], "%d", &sleep_time) == 0) sleep_time = DEFAULT_SLEEP_TIME; printf("Sleep time set to %d second(s).\n", sleep_time); while (1) { // Receive requests and spawn workers n = pk_receive(SRV_ID, &pckt_req, sizeof(pckt_req)); printf("%d byte/s received...\n", (int) n); spawn_worker(&pckt_req); } return 0; }
void mt_task_queue::wait_for_finish(gtask const & t) { if (!t || get_state(t).load() > task_state::Running) return; unique_lock<mutex> lock(m_mutex); submit_core(t, get_default_prio()); if (get_state(t).load() <= task_state::Running) { int additionally_required_workers = 0; if (g_current_task) { additionally_required_workers++; if (m_sleeping_workers == 0) { spawn_worker(); } else { m_wake_up_worker.notify_one(); } } scoped_add<int> inc_required(m_required_workers, additionally_required_workers); get_sched_info(t).wait(lock, [&] { return get_state(t).load() > task_state::Running; }); } switch (get_state(t).load()) { case task_state::Failed: case task_state::Success: return; default: throw exception("invalid task state"); } }
static void query(void) { struct query_list *q = free_queries; enum helper_exit_status r; /* find an unused queue entry */ if (q == NULL) { q = malloc(sizeof(*q)); if (q == NULL) { syslog(LOG_ERR, "malloc(3) failed"); exit(HES_MALLOC); } } else { free_queries = q->next; } r = read_pipe(PLUTO_QFD, (unsigned char *)&q->aq, sizeof(q->aq), sizeof(q->aq)); if (r == HES_OK) { /* EOF: we're done, except for unanswered queries */ struct worker_info *w; eof_from_pluto = TRUE; q->next = free_queries; free_queries = q; /* Send bye-bye to unbusy processes. * Note that if there are queued queries, there won't be * any non-busy workers. */ for (w = wi; w != wi_roof; w++) if (!w->busy) send_eof(w); } else if (r != HES_CONTINUE) { exit(r); } else if (q->aq.qmagic != ADNS_Q_MAGIC) { syslog(LOG_ERR, "error in query from Pluto: bad magic"); exit(HES_BAD_MAGIC); } else { struct worker_info *w; /* got a query */ /* add it to FIFO */ q->next = NULL; if (oldest_query == NULL) oldest_query = q; else newest_query->next = q; newest_query = q; /* See if any worker available */ for (w = wi;; w++) { if (w == wi_roof) { /* no free worker */ if (w == wi + MAX_WORKERS) break; /* no more to be created */ /* make a new one */ if (!spawn_worker()) break; /* cannot create one at this time */ } if (!w->busy) { /* assign first to free worker */ forward_query(w); break; } } } return; }
int main(int argc, char** argv) { /* * These counters will be used as offsets for messages when using pipes * i.e. write(stack + stack_pos, strlen(stack + stack_pos)) */ int stack_pos = 0; int input_pos = 1; char input[MAX_BUF_SIZE] = ""; char stack[MAX_BUF_SIZE] = ""; char result[MAX_BUF_SIZE] = ""; fgets(input, MAX_BUF_SIZE - 1, stdin); fgets(stack, MAX_BUF_SIZE - 1, stdin); fgets(result, MAX_BUF_SIZE - 1, stdin); input[strcspn(input, "\n")] = 0; stack[strcspn(stack, "\n")] = 0; result[strcspn(result, "\n")] = 0; if ((strlen(input) == 0)) // End of input, clearing stack { while (stack_pos < strlen(stack)) { write_to_result(result, ' '); write_to_result(result, stack[stack_pos++]); } if (debug) fprintf(stderr, "pid: %d end of input! result: %s \n", getpid(), result ); printf("%s", result); return 0; } if (debug) fprintf(stderr, "pid: %d input[0]: %c stack: %s result: %s \n", getpid(), input[0], stack, result ); switch (input[0]) { case '-': /* Odp.: Przez liczbę całkowitą należy rozumież liczbę całkowitą bez znaku */ case '^': case '*': case '/': case '+': while (stack_pos < strlen(stack)) { /* treating every op as left-associative */ if (op_priority(input[0]) <= op_priority(stack[stack_pos])) { write_to_result(result, ' '); write_to_result(result, stack[stack_pos++]); } else break; } write_to_result(result, ' '); case '(': write_to_stack(stack, input[0], &stack_pos); break; case ')': while(stack_pos <= strlen(stack)) { if (stack[stack_pos] != '(') { write_to_result(result, ' '); write_to_result(result, stack[stack_pos++]); } else { stack_pos++; break; } } case ' ': case '\n': break; default: add_space_to_result(result); /* * We only checked first character of expression (input[0]) * Now let's check if there are other characters in expression */ for (int i = 0; i < strlen(input); i++) { /* When there's no space around parenthesis * easier testing */ if (!isspace(input[i]) && (input[i] != ')')) { write_to_result(result, input[i]); } else { input_pos = i + ((input[i] != ')') ? (1) : (0)); break; } } break; } /* Moving offset to first nonwhite character in input */ while ((input_pos < strlen(input)) && (isspace(input[input_pos]))) input_pos++; spawn_worker(input + input_pos, stack + stack_pos, result); return 0; }
int main(int argc, char **argv) { struct timespec mtime = { 0 }; sigset_t mask, sigmask_orig; int c, fd; int ep_timeout = 0; int ignore_timer = 0; int new_events = 0; char *eventdir, *prog, **prog_args; struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "version", no_argument, 0, 'V' }, { "foreground", no_argument, 0, 'f' }, { "loglevel", required_argument, 0, 'L' }, { "logfile", required_argument, 0, 'l' }, { "pidfile", required_argument, 0, 'p' }, { "timeout", required_argument, 0, 't' }, { 0, 0, 0, 0 } }; while ((c = getopt_long(argc, argv, "hVfL:l:p:", long_options, NULL)) != -1) { switch (c) { case 't': timeout = atoi(optarg); if (!timeout) timeout = DEFAULT_TIMEOUT; break; case 'p': pidfile = optarg; break; case 'l': logfile = optarg; break; case 'L': log_priority = logging_level(optarg); break; case 'f': daemonize = 0; break; case 'V': printf("%s %s\n", PROGRAM_NAME, VERSION); return EXIT_SUCCESS; default: case 'h': printf("Usage: %s [options] DIRECTORY PROGRAM [ARGS...]\n" "\nThe utility monitors the DIRECTORY and when\n" "new files appear run the PROGRAM.\n\n" "Options:\n" " -p, --pidfile=FILE pid file location;\n" " -l, --logfile=FILE log file;\n" " -L, --loglevel=LVL logging level;\n" " -t, --timeout=SEC number of seconds that need to wait" " for files before the PROGRAM launch;\n" " -f, --foreground stay in the foreground;\n" " -V, --version print program version and exit;\n" " -h, --help show this text and exit.\n" "\n", PROGRAM_NAME); return EXIT_SUCCESS; } } if (optind >= argc) error(EXIT_FAILURE, 0, "You must specify the directory"); eventdir = argv[optind++]; if (optind >= argc) error(EXIT_FAILURE, 0, "You must specify the program"); prog = canonicalize_file_name(argv[optind]); if (!prog) error(EXIT_FAILURE, errno, "Bad program"); argv[optind] = strrchr(prog, '/'); if (!argv[optind]) argv[optind] = prog; prog_args = argv + optind; if (!log_priority) log_priority = logging_level("info"); if (pidfile && check_pid(pidfile)) error(EXIT_FAILURE, 0, "%s: already running", PROGRAM_NAME); if (chdir("/") < 0) error(EXIT_FAILURE, errno, "%s: chdir(/)", PROGRAM_NAME); close(STDIN_FILENO); if ((fd = open("/dev/null", O_RDONLY)) < 0) error(EXIT_FAILURE, errno, "%s: open(/dev/null)", PROGRAM_NAME); if (fd != STDIN_FILENO) { dup2(fd, STDIN_FILENO); close(fd); } if (daemonize && daemon(0, 1) < 0) error(EXIT_FAILURE, errno, "%s: daemon", PROGRAM_NAME); logging_init(); info("starting version %s", VERSION); if (pidfile && write_pid(pidfile) == 0) return EXIT_FAILURE; sigfillset(&mask); sigprocmask(SIG_SETMASK, &mask, &sigmask_orig); sigdelset(&mask, SIGABRT); sigdelset(&mask, SIGSEGV); if ((fd_ep = epoll_create1(EPOLL_CLOEXEC)) < 0) fatal("epoll_create1: %m"); if ((fd_signal = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC)) < 0) fatal("signalfd: %m"); epollin_add(fd_ep, fd_signal); if ((fd_eventdir = inotify_init1(IN_NONBLOCK | IN_CLOEXEC)) < 0) fatal("inotify_init1: %m"); if (inotify_add_watch(fd_eventdir, eventdir, IN_ONLYDIR | IN_DONT_FOLLOW | IN_MOVED_TO | IN_CLOSE_WRITE) < 0) fatal("inotify_add_watch: %m"); epollin_add(fd_ep, fd_eventdir); ignore_timer = is_dir_not_empty(eventdir); if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) fatal("clock_gettime: %m"); last.tv_sec = now.tv_sec; while (!do_exit) { struct epoll_event ev[42]; int i, fdcount; ssize_t size; if ((fdcount = epoll_wait(fd_ep, ev, ARRAY_SIZE(ev), ep_timeout)) < 0) continue; if (!ep_timeout) ep_timeout = timeout * 1000; for (i = 0; i < fdcount; i++) { if (!(ev[i].events & EPOLLIN)) { continue; } else if (ev[i].data.fd == fd_signal) { struct signalfd_siginfo fdsi; size = TEMP_FAILURE_RETRY(read(fd_signal, &fdsi, sizeof(struct signalfd_siginfo))); if (size != sizeof(struct signalfd_siginfo)) { err("unable to read signal info"); continue; } handle_signal(fdsi.ssi_signo); } else if (ev[i].data.fd == fd_eventdir) { read_inotify_events(fd_eventdir); new_events += 1; } } if (new_events) { struct stat sb; new_events = 0; if (lstat(eventdir, &sb) < 0) fatal("lstat: %s: %m", eventdir); if (mtime.tv_sec != sb.st_mtim.tv_sec || mtime.tv_nsec != sb.st_mtim.tv_nsec) { if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) fatal("clock_gettime: %m"); last.tv_sec = now.tv_sec; } mtime.tv_sec = sb.st_mtim.tv_sec; mtime.tv_nsec = sb.st_mtim.tv_nsec; } if (worker_pid) continue; if (!ignore_timer) { if (clock_gettime(CLOCK_MONOTONIC, &now) < 0) fatal("clock_gettime: %m"); if (now.tv_sec < last.tv_sec || (now.tv_sec - last.tv_sec) < timeout) continue; } ignore_timer = 0; if ((worker_pid = spawn_worker(prog, prog_args)) < 0) fatal("spawn_worker: %m"); dbg("Run worker %d", worker_pid); } epollin_remove(fd_ep, fd_signal); epollin_remove(fd_ep, fd_eventdir); free(prog); if (pidfile) remove_pid(pidfile); logging_close(); return EXIT_SUCCESS; }
int main(int argc, char *argv[]) { int rc = 1; int ret; signal(SIGINT, signal_handler); int c; char ep[28]; const char *host = "0.0.0.0"; char *ohost = NULL; int port = 48005; void *ctx = NULL; void *fe = NULL; void *be = NULL; while ((c = getopt (argc, argv, "h:p:")) != -1) switch (c) { case 'h': ohost = strdup(optarg); break; case 'p': port = atoi(optarg); } pid_t pid = spawn_worker(); printf("Spawned worker w/ pid %d\n", pid); if (ohost != NULL) host = ohost; snprintf(ep, 28, "tcp://%s:%d", host, port); if (ohost != NULL) free(ohost); ctx = zmq_ctx_new(); if (ctx == NULL) goto finished; fe = zmq_socket(ctx, ZMQ_ROUTER); if (fe == NULL) goto finished; be = zmq_socket(ctx, ZMQ_DEALER); if (be == NULL) goto finished; ret = zmq_bind(fe, ep); if (ret < 0) { fprintf(stderr, "Unable to bind socket\n"); goto finished; } zmq_bind(be, WORKER_IPC); zmq_pollitem_t items [] = { { fe, 0, ZMQ_POLLIN, 0 }, { be, 0, ZMQ_POLLIN, 0 } }; printf("Waiting for messages...\n"); void *cred; void *buf; int len; while (1) { zmq_msg_t message; zmq_msg_t out; ret = zmq_poll(items, 2, -1); if (ret < 0) if (errno == EINTR) { break; } if (items[0].revents & ZMQ_POLLIN) { while (1) { zmq_msg_init(&message); zmq_msg_recv(&message, fe, 0); int more = zmq_msg_more(&message); if (!more) { cred = zmq_msg_data(&message); munge_err_t err = munge_decode(cred, NULL, &buf, &len, NULL, NULL); if (err != EMUNGE_SUCCESS) fprintf(stderr, "Munge failed to decode\n"); zmq_msg_init_data(&out, buf, len, free_buf, NULL); zmq_msg_send(&out, be, 0); zmq_msg_close(&out); } else { zmq_msg_send(&message, be, more? ZMQ_SNDMORE: 0); } zmq_msg_close(&message); if (!more) break; } } if (items[1].revents & ZMQ_POLLIN) { while (1) { zmq_msg_init(&message); zmq_msg_recv(&message, be, 0); int more = zmq_msg_more(&message); zmq_msg_send(&message, fe, more? ZMQ_SNDMORE: 0); zmq_msg_close(&message); if (!more) break; } } } rc = 0; printf("Shutting down\n"); finished: printf("Stopping workers...\n"); pid_t w; int status; do { w = waitpid(pid, &status, 0); if (w == -1) { fprintf(stderr, "Unable to wait\n"); break; } } while (!WIFEXITED(status) && !WIFSIGNALED(status)); printf("Finishing cleanup\n"); ret = zmq_close(fe); if (ret < 0) fprintf(stderr, "Failed to close frontend socket\n"); ret = zmq_close(be); if (ret < 0) fprintf(stderr, "Failed to close backend socket\n"); ret = zmq_ctx_destroy(ctx); if(ret < 0) fprintf(stderr, "Failed to stop ZMQ\n"); return rc; }