地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【Nginx】SIGUSR1を受け取った後の処理をざっくり見ていく

ログローテートの記事を書くためのサンプルとしてとりあえず追っていく記事。ログローテートの設定は別でやる必要があるのでこの記事のサンプルで動作するときの流れをイメージして書いていく。

qiita.com

SIGUSR1はsrc/core/ngx_config.hでdefineされている

#define NGX_REOPEN_SIGNAL        USR1

masterがsrc/os/unix/ngx_process.c辺りでシグナルハンドラを設定する。シグナルが送られたらngx_reopenというフラグを立てる

        case ngx_signal_value(NGX_REOPEN_SIGNAL):
            ngx_reopen = 1;
            action = ", reopening logs";
            break;

ngx_master_process_cycleの中でreopenフラグが立っていると子プロセスにSIGUSR1を送出する。

        if (ngx_reopen) {
            ngx_reopen = 0;
            ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
            ngx_reopen_files(cycle, ccf->user);
            ngx_signal_worker_processes(cycle,
                                        ngx_signal_value(NGX_REOPEN_SIGNAL));
        }

子プロセスはngx_reopen_filesを呼び出す。

        if (ngx_reopen) {
            ngx_reopen = 0;
            ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "reopening logs");
            ngx_reopen_files(cycle, -1);
        }

ここが最終的に呼ばれる

void
ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user)
{
    ngx_fd_t          fd;
    ngx_uint_t        i;
    ngx_list_part_t  *part;
    ngx_open_file_t  *file;

    part = &cycle->open_files.part; // オープンしているファイル
    file = part->elts;

    for (i = 0; /* void */ ; i++) {

        if (i >= part->nelts) {
            if (part->next == NULL) { // 読み切ったらbreak
                break;
            }
            part = part->next;
            file = part->elts;
            i = 0;
        }

        if (file[i].name.len == 0) {
            continue;
        }

        if (file[i].flush) {
            file[i].flush(&file[i], cycle->log);
        }

        fd = ngx_open_file(file[i].name.data, NGX_FILE_APPEND,
                           NGX_FILE_CREATE_OR_OPEN, NGX_FILE_DEFAULT_ACCESS); // O_CRETEを指定しているので存在しなければ作成

        if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { // close処理は直後に実施
            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                          ngx_close_file_n " \"%s\" failed",
                          file[i].name.data);
        }

        file[i].fd = fd;
    }

    (void) ngx_log_redirect_stderr(cycle);
}

ざっくり読んだ。ログローテートに対応するログ監視ツールを書く場合に気をつけることという記事を次に書く予定。