int main(int argc, char *argv[]) { 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); signal(SIGPIPE, SIG_IGN); sighup = signal_register(SIGHUP); process_init(); ovsrec_init(); daemonize_start(); retval = unixctl_server_create(NULL, &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) { if (signal_poll(sighup)) { vlog_reopen_log_file(); } bridge_run_fast(); bridge_run(); bridge_run_fast(); unixctl_server_run(unixctl); netdev_run(); signal_wait(sighup); bridge_wait(); unixctl_server_wait(unixctl); netdev_wait(); if (exiting) { poll_immediate_wake(); } poll_block(); } bridge_exit(); unixctl_server_destroy(unixctl); signal_unregister(sighup); return 0; }
/* Processes incoming requests for 'server'. */ static void poll_server(int fd UNUSED, short int events UNUSED, void *server_) { struct vlog_server *server = server_; for (;;) { char cmd_buf[512]; struct sockaddr_un un; socklen_t un_len; char *reply; int error; error = recv_with_creds(server, cmd_buf, sizeof cmd_buf, &un, &un_len); if (error > 0) { if (error != EAGAIN && error != EWOULDBLOCK) { fprintf(stderr, "vlog: reading configuration socket: %s", strerror(errno)); } break; } else if (error < 0) { continue; } /* Process message and send reply. */ if (!strncmp(cmd_buf, "set ", 4)) { char *msg = vlog_set_levels_from_string(cmd_buf + 4); reply = msg ? msg : xstrdup("ack"); } else if (!strcmp(cmd_buf, "list")) { reply = vlog_get_levels(); } else if (!strcmp(cmd_buf, "reopen")) { int error = vlog_reopen_log_file(); reply = (error ? xasprintf("could not reopen log file \"%s\": %s", vlog_get_log_file(), strerror(error)) : xstrdup("ack")); } else { reply = xstrdup("nak"); } sendto(server->fd, reply, strlen(reply), 0, (struct sockaddr*) &un, un_len); free(reply); } server->waiter = poll_fd_callback(server->fd, POLLIN, poll_server, server); }
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]); service_start(&argc, &argv); remote = parse_options(argc, argv, &unixctl_path); signal(SIGPIPE, SIG_IGN); sighup = signal_register(SIGHUP); 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 } 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) { 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(); unixctl_server_run(unixctl); netdev_run(); signal_wait(sighup); memory_wait(); bridge_wait(); unixctl_server_wait(unixctl); netdev_wait(); if (exiting) { poll_immediate_wake(); } poll_block(); if (should_service_stop()) { exiting = true; } } bridge_exit(); unixctl_server_destroy(unixctl); service_stop(); return 0; }
static void monitor_daemon(pid_t daemon_pid) { /* XXX Should log daemon's stderr output at startup time. */ time_t last_restart; char *status_msg; int crashes; bool child_ready = true; set_subprogram_name("monitor"); status_msg = xstrdup("healthy"); last_restart = TIME_MIN; crashes = 0; for (;;) { int retval; int status; ovs_cmdl_proctitle_set("monitoring pid %lu (%s)", (unsigned long int) daemon_pid, status_msg); if (child_ready) { int error; do { retval = waitpid(daemon_pid, &status, 0); error = retval == -1 ? errno : 0; } while (error == EINTR); vlog_reopen_log_file(); if (error) { VLOG_FATAL("waitpid failed (%s)", ovs_strerror(error)); } } if (!child_ready || retval == daemon_pid) { char *s = process_status_msg(status); if (should_restart(status)) { free(status_msg); status_msg = xasprintf("%d crashes: pid %lu died, %s", ++crashes, (unsigned long int) daemon_pid, s); free(s); if (WCOREDUMP(status)) { /* Disable further core dumps to save disk space. */ struct rlimit r; r.rlim_cur = 0; r.rlim_max = 0; if (setrlimit(RLIMIT_CORE, &r) == -1) { VLOG_WARN("failed to disable core dumps: %s", ovs_strerror(errno)); } } /* Throttle restarts to no more than once every 10 seconds. */ if (time(NULL) < last_restart + 10) { VLOG_WARN("%s, waiting until 10 seconds since last " "restart", status_msg); for (;;) { time_t now = time(NULL); time_t wakeup = last_restart + 10; if (now >= wakeup) { break; } xsleep(wakeup - now); } } last_restart = time(NULL); VLOG_ERR("%s, restarting", status_msg); child_ready = !fork_and_wait_for_startup(&daemonize_fd, &daemon_pid); if (child_ready && !daemon_pid) { /* Child process needs to break out of monitoring * loop. */ break; } } else { VLOG_INFO("pid %lu died, %s, exiting", (unsigned long int) daemon_pid, s); free(s); exit(0); } } } free(status_msg); /* Running in new daemon process. */ ovs_cmdl_proctitle_restore(); set_subprogram_name(""); }