static int worker_run(struct worker *self) { char buf[BUFFER_SIZE]; struct sigaction term_sa = { .sa_handler = SIG_IGN, .sa_flags = 0, }; struct queue *q = self->q; sigaction(SIGTTIN, &term_sa, NULL); while (1) { if (!queue_pop(q, buf)) break; read_test(buf); } queue_destroy(q, 1); tst_flush(); return 0; } static void spawn_workers(void) { int i; struct worker *wa = workers; bzero(workers, worker_count * sizeof(*workers)); for (i = 0; i < worker_count; i++) { wa[i].q = queue_init(); wa[i].pid = SAFE_FORK(); if (!wa[i].pid) exit(worker_run(wa + i)); } }
int main(int argc, char *argv[]) { char *unixctl_path = NULL; struct unixctl_server *unixctl; struct signal *sighup; char *remote; bool exiting; int retval; proctitle_init(argc, argv); set_program_name(argv[0]); stress_init_command(); remote = parse_options(argc, argv, &unixctl_path); signal(SIGPIPE, SIG_IGN); sighup = signal_register(SIGHUP); process_init(); ovsrec_init(); daemonize_start(); if (want_mlockall) { #ifdef HAVE_MLOCKALL if (mlockall(MCL_CURRENT | MCL_FUTURE)) { VLOG_ERR("mlockall failed: %s", ovs_strerror(errno)); } #else VLOG_ERR("mlockall not supported on this system"); #endif } worker_start(); retval = unixctl_server_create(unixctl_path, &unixctl); if (retval) { exit(EXIT_FAILURE); } unixctl_command_register("exit", "", 0, 0, ovs_vswitchd_exit, &exiting); bridge_init(remote); free(remote); exiting = false; while (!exiting) { worker_run(); if (signal_poll(sighup)) { vlog_reopen_log_file(); } memory_run(); if (memory_should_report()) { struct simap usage; simap_init(&usage); bridge_get_memory_usage(&usage); memory_report(&usage); simap_destroy(&usage); } bridge_run_fast(); bridge_run(); bridge_run_fast(); unixctl_server_run(unixctl); netdev_run(); worker_wait(); signal_wait(sighup); memory_wait(); bridge_wait(); unixctl_server_wait(unixctl); netdev_wait(); if (exiting) { poll_immediate_wake(); } poll_block(); } bridge_exit(); unixctl_server_destroy(unixctl); return 0; }
static int worker_run(struct worker *self) { char buf[BUFFER_SIZE]; struct sigaction term_sa = { .sa_handler = SIG_IGN, .sa_flags = 0, }; struct queue *q = self->q; sigaction(SIGTTIN, &term_sa, NULL); while (1) { if (!queue_pop(q, buf)) break; read_test(buf); } queue_destroy(q, 1); tst_flush(); return 0; } static void maybe_drop_privs(void) { struct passwd *nobody; if (!drop_privs) return; TEST(setgroups(0, NULL)); if (TST_RET < 0 && TST_ERR != EPERM) { tst_brk(TBROK | TTERRNO, "Failed to clear suplementary group set"); } nobody = SAFE_GETPWNAM("nobody"); TEST(setgid(nobody->pw_gid)); if (TST_RET < 0 && TST_ERR != EPERM) tst_brk(TBROK | TTERRNO, "Failed to use nobody gid"); TEST(setuid(nobody->pw_uid)); if (TST_RET < 0 && TST_ERR != EPERM) tst_brk(TBROK | TTERRNO, "Failed to use nobody uid"); } static void spawn_workers(void) { int i; struct worker *wa = workers; bzero(workers, worker_count * sizeof(*workers)); for (i = 0; i < worker_count; i++) { wa[i].q = queue_init(); wa[i].pid = SAFE_FORK(); if (!wa[i].pid) { maybe_drop_privs(); exit(worker_run(wa + i)); } } }