view src/os/unix/ngx_process.c @ 279:b79f021a644a

nginx-0.0.2-2004-03-04-19:34:23 import
author Igor Sysoev <igor@sysoev.ru>
date Thu, 04 Mar 2004 16:34:23 +0000
parents d4e65d74db9f
children 6b91bfbc4123
line wrap: on
line source


#include <ngx_config.h>
#include <ngx_core.h>


static void ngx_execute_proc(ngx_cycle_t *cycle, void *data);

ngx_uint_t     ngx_last_process;
ngx_process_t  ngx_processes[NGX_MAX_PROCESSES];


ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle,
                            ngx_spawn_proc_pt proc, void *data,
                            char *name, ngx_int_t respawn)
{
    ngx_pid_t  pid;

    pid = fork();

    if (pid == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "fork() failed while spawning \"%s\"", name);
    }

    switch (pid) {
    case -1:
        return NGX_ERROR;

    case 0:
        ngx_pid = ngx_getpid();
        proc(cycle, data);
        break;

    default:
        break;
    }

    ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
                   "spawn %s: " PID_T_FMT, name, pid);

    if (respawn >= 0) {
        ngx_processes[respawn].pid = pid;
        ngx_processes[respawn].exited = 0;
        return pid;
    }

    ngx_processes[ngx_last_process].pid = pid;
    ngx_processes[ngx_last_process].proc = proc;
    ngx_processes[ngx_last_process].data = data;
    ngx_processes[ngx_last_process].name = name;
    ngx_processes[ngx_last_process].respawn =
                                      (respawn == NGX_PROCESS_RESPAWN) ? 1 : 0;
    ngx_processes[ngx_last_process].detached =
                                     (respawn == NGX_PROCESS_DETACHED) ? 1 : 0;
    ngx_processes[ngx_last_process].exited = 0;
    ngx_processes[ngx_last_process].exiting = 0;
    ngx_last_process++;

    return pid;
}


ngx_pid_t ngx_execute(ngx_cycle_t *cycle, ngx_exec_ctx_t *ctx)
{
    return ngx_spawn_process(cycle, ngx_execute_proc, ctx, ctx->name,
                             NGX_PROCESS_DETACHED);
}


static void ngx_execute_proc(ngx_cycle_t *cycle, void *data)
{
    ngx_exec_ctx_t  *ctx = data;

    if (execve(ctx->path, ctx->argv, ctx->envp) == -1) {
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "execve() failed while executing %s \"%s\"",
                      ctx->name, ctx->path);
    }

    exit(1);
}


void ngx_respawn_processes(ngx_cycle_t *cycle)
{
    ngx_uint_t  i;

    for (i = 0; i < ngx_last_process; i++) {

        if (ngx_processes[i].exiting || !ngx_processes[i].exited) {
            continue;
        }

        if (!ngx_processes[i].respawn) {
            if (i != --ngx_last_process) {
                ngx_processes[i--] = ngx_processes[ngx_last_process];
            }
            continue;
        }

        if (ngx_spawn_process(cycle,
                              ngx_processes[i].proc, ngx_processes[i].data,
                              ngx_processes[i].name, i) == NGX_ERROR)
        {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "can not respawn %s", ngx_processes[i].name);
        }
    }
}


void ngx_process_get_status()
{
    int              status;
    char            *process;
    ngx_pid_t        pid;
    ngx_err_t        err;
    ngx_uint_t       i, one;
    struct timeval   tv;
    one = 0;

    for ( ;; ) {
        pid = waitpid(-1, &status, WNOHANG);

        if (pid == 0) {
            return;
        }

        if (pid == -1) {
            err = ngx_errno;

            if (err == NGX_EINTR) {
                continue;
            }

            if (err == NGX_ECHILD && one) {
                return;
            }

            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, errno,
                          "waitpid() failed");
            return;
        }

        one = 1;
        process = "";

        for (i = 0; i < ngx_last_process; i++) {
            if (ngx_processes[i].pid == pid) {
                ngx_processes[i].status = status;
                ngx_processes[i].exited = 1;
                process = ngx_processes[i].name;
                break;
            }
        }

        if (i == ngx_last_process) {
            process = "unknown process";
        }

        if (WTERMSIG(status)) {
            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                          "%s " PID_T_FMT " exited on signal %d%s",
                          process, pid, WTERMSIG(status),
                          WCOREDUMP(status) ? " (core dumped)" : "");

        } else {
            ngx_log_error(NGX_LOG_INFO, ngx_cycle->log, 0,
                          "%s " PID_T_FMT " exited with code %d",
                          process, pid, WEXITSTATUS(status));
        }

        if (WEXITSTATUS(status) == 2 && ngx_processes[i].respawn) {
            ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                          "%s " PID_T_FMT
                          " exited with fatal code %d and could not respawn",
                          process, pid, WEXITSTATUS(status));
            ngx_processes[i].respawn = 0;
        }
    }
}