/* Initializes the fatal signal handling module.  Calling this function is
 * optional, because calling any other function in the module will also
 * initialize it.  However, in a multithreaded program, the module must be
 * initialized while the process is still single-threaded. */
void
fatal_signal_init(void)
{
    static bool inited = false;

    if (!inited) {
        size_t i;

        assert_single_threaded();
        inited = true;

        ovs_mutex_init_recursive(&mutex);
        xpipe_nonblocking(signal_fds);

        for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) {
            int sig_nr = fatal_signals[i];
            struct sigaction old_sa;

            xsigaction(sig_nr, NULL, &old_sa);
            if (old_sa.sa_handler == SIG_DFL
                && signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
        }
        atexit(atexit_handler);
    }
}
Beispiel #2
0
/* Sets up a following call to daemonize() to create a pidfile named 'name'.
 * If 'name' begins with '/', then it is treated as an absolute path.
 * Otherwise, it is taken relative to RUNDIR, which is $(prefix)/var/run by
 * default.
 *
 * If 'name' is null, then program_name followed by ".pid" is used. */
void
set_pidfile(const char *name)
{
    assert_single_threaded();
    free(pidfile);
    pidfile = make_pidfile_name(name);
}
Beispiel #3
0
/* Noramlly, user switch is embedded within daemonize_start().
 * However, there in case the user switch needs to be done
 * before daemonize_start(), the following API can be used.  */
void
daemon_become_new_user(bool access_datapath)
{
    assert_single_threaded();
    if (switch_user) {
        daemon_become_new_user__(access_datapath);
        /* daemonize_start() should not switch user again. */
        switch_user = false;
    }
}
Beispiel #4
0
/* If daemonization is configured, then starts daemonization, by forking and
 * returning in the child process.  The parent process hangs around until the
 * child lets it know either that it completed startup successfully (by calling
 * daemon_complete()) or that it failed to start up (by exiting with a nonzero
 * exit code). */
void
daemonize_start(bool access_datapath)
{
    assert_single_threaded();
    daemonize_fd = -1;

    if (switch_user) {
        daemon_become_new_user__(access_datapath);
        switch_user = false;
    }

    if (detach) {
        pid_t pid;

        if (fork_and_wait_for_startup(&daemonize_fd, &pid)) {
            VLOG_FATAL("could not detach from foreground session");
        }
        if (pid > 0) {
            /* Running in parent process. */
            exit(0);
        }

        /* Running in daemon or monitor process. */
        setsid();
    }

    if (monitor) {
        int saved_daemonize_fd = daemonize_fd;
        pid_t daemon_pid;

        if (fork_and_wait_for_startup(&daemonize_fd, &daemon_pid)) {
            VLOG_FATAL("could not initiate process monitoring");
        }
        if (daemon_pid > 0) {
            /* Running in monitor process. */
            fork_notify_startup(saved_daemonize_fd);
            if (detach) {
                close_standard_fds();
            }
            monitor_daemon(daemon_pid);
        }
        /* Running in daemon process. */
    }

    forbid_forking("running in daemon process");

    if (pidfile) {
        make_pidfile();
    }

    /* Make sure that the unixctl commands for vlog get registered in a
     * daemon, even before the first log message. */
    vlog_init();
}
Beispiel #5
0
/* Configures the program to die with SIGALRM 'secs' seconds from now, if
 * 'secs' is nonzero, or disables the feature if 'secs' is zero. */
void
time_alarm(unsigned int secs)
{
    long long int now;
    long long int msecs;

    assert_single_threaded();
    time_init();

    now = time_msec();
    msecs = secs * 1000LL;
    deadline = now < LLONG_MAX - msecs ? now + msecs : LLONG_MAX;
}
Beispiel #6
0
/* Initializes the fatal signal handling module.  Calling this function is
 * optional, because calling any other function in the module will also
 * initialize it.  However, in a multithreaded program, the module must be
 * initialized while the process is still single-threaded. */
void
fatal_signal_init(void)
{
    static bool inited = false;

    if (!inited) {
        size_t i;

        assert_single_threaded();
        inited = true;

        ovs_mutex_init_recursive(&mutex);
#ifndef _WIN32
        xpipe_nonblocking(signal_fds);
#else
        wevent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!wevent) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to create a event (%s).", msg_buf);
        }

        /* Register a function to handle Ctrl+C. */
        SetConsoleCtrlHandler(ConsoleHandlerRoutine, true);
#endif

        for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) {
            int sig_nr = fatal_signals[i];
#ifndef _WIN32
            struct sigaction old_sa;

            xsigaction(sig_nr, NULL, &old_sa);
            if (old_sa.sa_handler == SIG_DFL
                && signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
#else
            if (signal(sig_nr, fatal_signal_handler) == SIG_ERR) {
                VLOG_FATAL("signal failed (%s)", ovs_strerror(errno));
            }
#endif
        }
        atexit(fatal_signal_atexit_handler);
    }
}
Beispiel #7
0
/* If daemonization is configured, then starts daemonization, by forking and
 * returning in the child process.  The parent process hangs around until the
 * child lets it know either that it completed startup successfully (by calling
 * daemon_complete()) or that it failed to start up (by exiting with a nonzero
 * exit code). */
void
daemonize_start(void)
{
    assert_single_threaded();
    daemonize_fd = -1;

    if (detach) {
        if (fork_and_wait_for_startup(&daemonize_fd) > 0) {
            /* Running in parent process. */
            exit(0);
        }

        /* Running in daemon or monitor process. */
        setsid();
    }

    if (monitor) {
        int saved_daemonize_fd = daemonize_fd;
        pid_t daemon_pid;

        daemon_pid = fork_and_wait_for_startup(&daemonize_fd);
        if (daemon_pid > 0) {
            /* Running in monitor process. */
            fork_notify_startup(saved_daemonize_fd);
            close_standard_fds();
            monitor_daemon(daemon_pid);
        }
        /* Running in daemon process. */
    }

    forbid_forking("running in daemon process");

    if (pidfile) {
        make_pidfile();
    }

    /* Make sure that the unixctl commands for vlog get registered in a
     * daemon, even before the first log message. */
    vlog_init();
}
Beispiel #8
0
void
add_allowed_ofp_versions(uint32_t bitmap)
{
    assert_single_threaded();
    allowed_versions |= bitmap;
}
Beispiel #9
0
void
set_allowed_ofp_versions(const char *string)
{
    assert_single_threaded();
    allowed_versions = ofputil_versions_from_string(string);
}
/* Registers the call-back and configures the actions in case of a failure
 * with the Windows services manager. */
void
service_start(int *argcp, char **argvp[])
{
    int argc = *argcp;
    char **argv = *argvp;
    int i;
    SERVICE_TABLE_ENTRY service_table[] = {
        {(LPTSTR)program_name, (LPSERVICE_MAIN_FUNCTION)main},
        {NULL, NULL}
    };

    /* 'detached' is 'false' when service_start() is called the first time.
     * It is 'true', when it is called the second time by the Windows services
     * manager. */
    if (detached) {
        init_service_status();

        wevent = CreateEvent(NULL, TRUE, FALSE, NULL);
        if (!wevent) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to create a event (%s).", msg_buf);
        }

        poll_fd_wait_event(0, wevent, POLLIN);

        /* Register the control handler. This function is called by the service
         * manager to stop the service. */
        hstatus = RegisterServiceCtrlHandler(program_name,
                                         (LPHANDLER_FUNCTION)control_handler);
        if (!hstatus) {
            char *msg_buf = ovs_lasterror_to_string();
            VLOG_FATAL("Failed to register the service control handler (%s).",
                        msg_buf);
        }

        if (monitor) {
            set_config_failure_actions();
        }

        /* When the service control manager does the call back, it does not
         * send the same arguments as sent to the main function during the
         * service start. So, use the arguments passed over during the first
         * time. */
        *argcp = sargc;
        *argvp = *sargvp;

        /* XXX: Windows implementation cannot have a unixctl commands in the
        * traditional sense of unix domain sockets. If an implementation is
        * done that involves 'unixctl' vlog commands the following call is
        * needed to make sure that the unixctl commands for vlog get
        * registered in a daemon, even before the first log message. */
        vlog_init();

        return;
    }

    assert_single_threaded();

    /* A reference to arguments passed to the main function the first time.
     * We need it after the call-back from service control manager. */
    sargc = argc;
    sargvp = argvp;

    /* We are only interested in the '--service' and '--service-monitor'
     * options before the call-back from the service control manager. */
    for (i = 0; i < argc; i ++) {
        if (!strcmp(argv[i], "--service")) {
            detach = true;
        } else if (!strcmp(argv[i], "--service-monitor")) {
            monitor = true;
        }
    }

    /* If '--service' is not a command line option, run in foreground. */
    if (!detach) {
        return;
    }

    /* If we have been configured to run as a service, then that service
     * should already have been created either manually or through a start up
     * script. */
    check_service();

    detached = true;

    /* StartServiceCtrlDispatcher blocks and returns after the service is
     * stopped. */
    if (!StartServiceCtrlDispatcher(service_table)) {
        char *msg_buf = ovs_lasterror_to_string();
        VLOG_FATAL("Failed at StartServiceCtrlDispatcher (%s)", msg_buf);
    }
    exit(0);
}