Beispiel #1
0
// Syscall API
int task_signal_syscall(task_t* source, isf_t* state, int target_pid, int sig) {
	task_t* target_task = scheduler_find(target_pid);
	if(!target_task) {
		sc_errno = ESRCH;
		return -1;
	}

	if(target_task->euid != source->euid) {
		sc_errno = EPERM;
		return -1;
	}

	/* POSIX: "If sig is 0 (the null signal), error checking is performed but
	 * no signal is actually sent. The null signal can be used to check the
	 * validity of pid."
	 */
	if(!sig) {
		return 0;
	}

	return task_signal(target_task, source, sig, state);
}
Beispiel #2
0
__sighandler_t sys_signal(int signum, __sighandler_t handler) {
	return task_signal(CurrentTask, signum, handler);
}
Beispiel #3
0
int
dmon_main (int argc, char **argv)
{
    w_io_t *pidfile_io = NULL;
    char *opts_env = NULL;
    bool success;
    unsigned i, consumed;

    /* Check for "-C configfile" given in the command line. */
    if (argc > 2 && ((argv[1][0] == '-' &&
                      argv[1][1] == 'C' &&
                      argv[1][2] == '\0') ||
                     !strcmp ("--config", argv[1])))

    {
        w_lobj w_io_t *cfg_io = NULL;
        char *err_msg = NULL;

        if ((cfg_io = w_io_unix_open (argv[2], O_RDONLY, 0)) == NULL)
            w_die ("$s: Could not open file '$s', $E\n", argv[0], argv[2]);

        success = w_opt_parse_io (dmon_options, cfg_io, &err_msg);

        if (!success || err_msg)
            w_die ("$s: Error parsing '$s' at line $s\n", argv[0], argv[2], err_msg);

        replace_args_shift (2, &argc, &argv);
    }

    if ((opts_env = getenv ("DMON_OPTIONS")) != NULL)
        replace_args_string (opts_env, &argc, &argv);

    i = consumed = w_opt_parse (dmon_options, NULL, NULL,
                                "cmd [cmd-options] [ -- "
                                "log-cmd [log-cmd-options]]",
                                argc, argv);

    W_DEBUG ("w_opt_parse consumed $I arguments\n", consumed);

    if (workdir_path) {
        if (chdir (workdir_path) != 0)
            w_die ("$s: Cannot use '$s' as work directory, $E\n", argv[0], workdir_path);
    }

    if (status_path) {
        status_io = w_io_unix_open (status_path, O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (!status_io)
            w_die ("$s: Cannot open '$s' for writing, $E\n", argv[0], status_path);
    }

    if (cmd_interval && success_exit)
        w_die ("$s: Options '-i' and '-1' cannot be used together.\n", argv[0]);

    if (load_enabled && almost_zerof (load_low))
        load_low = load_high / 2.0f;

    cmd_task.argv = argv + consumed;

    /* Skip over until "--" is found */
    while (i < (unsigned) argc && strcmp (argv[i], "--") != 0) {
        cmd_task.argc++;
        i++;
    }

    /* There is a log command */
    if (i < (unsigned) argc && strcmp (argv[i], "--") == 0) {
        log_task.argc = argc - cmd_task.argc - consumed - 1;
        log_task.argv = argv + argc - log_task.argc;
        log_task.argv[log_task.argc] = NULL;
    }

    cmd_task.argv[cmd_task.argc] = NULL;

    if (log_task.argc > 0) {
        if (pipe (log_fds) != 0) {
            w_die ("$s: Cannot create pipe: $E\n", argv[0]);
        }
        W_DEBUG ("pipe_read = $i, pipe_write = $i\n", log_fds[0], log_fds[1]);
        fd_cloexec (log_fds[0]);
        fd_cloexec (log_fds[1]);
    }

#ifdef _DEBUG_PRINT
    {
        char **xxargv = cmd_task.argv;
        w_io_format (w_stderr, "cmd:");
        while (*xxargv) w_io_format (w_stderr, " $s", *xxargv++);
        w_io_format (w_stderr, "\n");
        if (log_enabled) {
            char **xxargv = log_task.argv;
            w_io_format (w_stderr, "log:");
            while (*xxargv) w_io_format (w_stderr, " $c", *xxargv++);
            w_io_format (w_stderr, "\n");
        }
    }
#endif /* _DEBUG_PRINT */

    if (cmd_task.argc == 0)
        w_die ("$s: No command to run given.\n", argv[0]);

    if (pidfile_path) {
        pidfile_io = w_io_unix_open (pidfile_path,
                                     O_TRUNC | O_CREAT | O_WRONLY,
                                     0666);
        if (!pidfile_io) {
            w_die ("$s: cannot open '$s' for writing: $E\n",
                   argv[0], pidfile_path);
        }
    }

    if (!nodaemon)
        become_daemon ();

    /* We have a valid file descriptor: write PID */
    if (pidfile_io) {
        w_io_result_t r = w_io_format (pidfile_io,
                                       "$L\n",
                                       (unsigned long) getpid ());
        if (w_io_failed (r))
            W_WARN ("I/O error writing to PID file: $E\n");
        w_obj_unref (pidfile_io);
    }

    setup_signals ();
    alarm (cmd_timeout);

    cmd_task.write_fd = log_fds[1];
    log_task.read_fd  = log_fds[0];

    while (running) {
        W_DEBUG (">>> loop iteration\n");
        if (check_child) {
            int retcode = reap_and_check ();

            /*
             * Wait the specified timeout but DO NOT use safe_sleep(): here
             * we want an interruptible sleep-wait so reaction to signals is
             * quick, which we definitely want for SIGINT/SIGTERM.
             */
            if (cmd_interval && !success_exit && retcode == 0) {
                int retval;
                struct timespec ts;
                ts.tv_sec = cmd_interval;
                ts.tv_nsec = 0;

                do {
                    retval = nanosleep (&ts, &ts);
                    W_DEBUGC ("  nanosleep -> $i\n", retval);
                } while (retval == -1 && errno == EINTR && running);
            }

            /*
             * Either handling signals which interrupt the previous loop,
             * or reap_and_check() may request stopping on successful exit
             */
            if (!running) {
                task_action_queue (&cmd_task, A_NONE);
                break;
            }
        }

        task_action_dispatch_and_write_status ("cmd", &cmd_task);
        if (log_enabled)
            task_action_dispatch_and_write_status ("log", &log_task);

        if (load_enabled) {
            double load_cur;

            W_DEBUGC ("  checking load after sleeping 1s\n");
            interruptible_sleep (1);

            if (getloadavg (&load_cur, 1) == -1)
                W_WARN ("getloadavg() failed: $E\n");

            if (paused) {
                /* If the current load dropped below load_low -> resume */
                if (load_cur <= load_low) {
                    W_DEBUGC ("  resuming...\n");
                    task_signal (&cmd_task, SIGCONT);
                    write_status ("cmd resume $L\n", (unsigned long) cmd_task.pid);
                    paused = 0;
                }
            }
            else {
                /* If the load went above load_high -> pause */
                if (load_cur > load_high) {
                    W_DEBUGC ("  pausing...\n");
                    task_signal (&cmd_task, SIGSTOP);
                    write_status ("cmd pause $L\n", (unsigned long) cmd_task.pid);
                    paused = 1;
                }
            }
        }
        else {
            /* Wait for signals to arrive. */
            W_DEBUGC ("  waiting for signals to come...\n");
            pause ();
        }
    }

    W_DEBUG ("exiting gracefully...\n");

    if (cmd_task.pid != NO_PID) {
        write_status ("cmd stop $L\n", (unsigned long) cmd_task.pid);
        task_action (&cmd_task, A_STOP);
    }
    if (log_enabled && log_task.pid != NO_PID) {
        write_status ("log stop $L\n", (unsigned long) log_task.pid);
        task_action (&log_task, A_STOP);
    }

    if (status_io) {
        w_obj_unref (status_io);
        status_io = NULL;
    }

    exit (EXIT_SUCCESS);
}