src/core/nginx.c - nginx-1.31.7 nginx/ @ 939334eff

Global variables defined

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <nginx.h>


  8. static void ngx_show_version_info(void);
  9. static ngx_int_t ngx_add_inherited_sockets(ngx_cycle_t *cycle);
  10. static void ngx_cleanup_environment(void *data);
  11. static void ngx_cleanup_environment_variable(void *data);
  12. static ngx_int_t ngx_get_options(int argc, char *const *argv);
  13. static ngx_int_t ngx_process_options(ngx_cycle_t *cycle);
  14. static ngx_int_t ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv);
  15. static void *ngx_core_module_create_conf(ngx_cycle_t *cycle);
  16. static char *ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf);
  17. static char *ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  18. static char *ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  19. static char *ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  20. static char *ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd,
  21.     void *conf);
  22. static char *ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd,
  23.     void *conf);
  24. static char *ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  25. #if (NGX_HAVE_DLOPEN)
  26. static void ngx_unload_module(void *data);
  27. #endif


  28. ‌static ngx_conf_enum_t  ngx_debug_points[] = {
  29.     { ngx_string("stop"), NGX_DEBUG_POINTS_STOP },
  30.     { ngx_string("abort"), NGX_DEBUG_POINTS_ABORT },
  31.     { ngx_null_string, 0 }
  32. };


  33. ‌static ngx_command_t  ngx_core_commands[] = {

  34.     { ngx_string("daemon"),
  35.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  36.       ngx_conf_set_flag_slot,
  37.       0,
  38.       offsetof(ngx_core_conf_t, daemon),
  39.       NULL },

  40.     { ngx_string("master_process"),
  41.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG,
  42.       ngx_conf_set_flag_slot,
  43.       0,
  44.       offsetof(ngx_core_conf_t, master),
  45.       NULL },

  46.     { ngx_string("timer_resolution"),
  47.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  48.       ngx_conf_set_msec_slot,
  49.       0,
  50.       offsetof(ngx_core_conf_t, timer_resolution),
  51.       NULL },

  52.     { ngx_string("pid"),
  53.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  54.       ngx_conf_set_str_slot,
  55.       0,
  56.       offsetof(ngx_core_conf_t, pid),
  57.       NULL },

  58.     { ngx_string("lock_file"),
  59.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  60.       ngx_conf_set_str_slot,
  61.       0,
  62.       offsetof(ngx_core_conf_t, lock_file),
  63.       NULL },

  64.     { ngx_string("worker_processes"),
  65.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  66.       ngx_set_worker_processes,
  67.       0,
  68.       0,
  69.       NULL },

  70.     { ngx_string("debug_points"),
  71.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  72.       ngx_conf_set_enum_slot,
  73.       0,
  74.       offsetof(ngx_core_conf_t, debug_points),
  75.       &ngx_debug_points },

  76.     { ngx_string("user"),
  77.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE12,
  78.       ngx_set_user,
  79.       0,
  80.       0,
  81.       NULL },

  82.     { ngx_string("worker_priority"),
  83.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  84.       ngx_set_priority,
  85.       0,
  86.       0,
  87.       NULL },

  88.     { ngx_string("worker_cpu_affinity"),
  89.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_1MORE,
  90.       ngx_set_cpu_affinity,
  91.       0,
  92.       0,
  93.       NULL },

  94.     { ngx_string("worker_rlimit_nofile"),
  95.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  96.       ngx_conf_set_num_slot,
  97.       0,
  98.       offsetof(ngx_core_conf_t, rlimit_nofile),
  99.       NULL },

  100.     { ngx_string("worker_rlimit_core"),
  101.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  102.       ngx_conf_set_off_slot,
  103.       0,
  104.       offsetof(ngx_core_conf_t, rlimit_core),
  105.       NULL },

  106.     { ngx_string("worker_shutdown_timeout"),
  107.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  108.       ngx_conf_set_msec_slot,
  109.       0,
  110.       offsetof(ngx_core_conf_t, shutdown_timeout),
  111.       NULL },

  112.     { ngx_string("working_directory"),
  113.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  114.       ngx_conf_set_str_slot,
  115.       0,
  116.       offsetof(ngx_core_conf_t, working_directory),
  117.       NULL },

  118.     { ngx_string("env"),
  119.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  120.       ngx_set_env,
  121.       0,
  122.       0,
  123.       NULL },

  124.     { ngx_string("load_module"),
  125.       NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
  126.       ngx_load_module,
  127.       0,
  128.       0,
  129.       NULL },

  130.       ngx_null_command
  131. };


  132. ‌static ngx_core_module_t  ngx_core_module_ctx = {
  133.     ngx_string("core"),
  134.     ngx_core_module_create_conf,
  135.     ngx_core_module_init_conf
  136. };


  137. ‌ngx_module_t  ngx_core_module = {
  138.     NGX_MODULE_V1,
  139.     &ngx_core_module_ctx,                  /* module context */
  140.     ngx_core_commands,                     /* module directives */
  141.     NGX_CORE_MODULE,                       /* module type */
  142.     NULL,                                  /* init master */
  143.     NULL,                                  /* init module */
  144.     NULL,                                  /* init process */
  145.     NULL,                                  /* init thread */
  146.     NULL,                                  /* exit thread */
  147.     NULL,                                  /* exit process */
  148.     NULL,                                  /* exit master */
  149.     NGX_MODULE_V1_PADDING
  150. };


  151. ‌static ngx_uint_t   ngx_show_help;
  152. ‌static ngx_uint_t   ngx_show_version;
  153. ‌static ngx_uint_t   ngx_show_configure;
  154. ‌static u_char      *ngx_prefix;
  155. ‌static u_char      *ngx_error_log;
  156. ‌static u_char      *ngx_conf_file;
  157. ‌static u_char      *ngx_conf_params;
  158. #if (NGX_CONTROL_API)
  159. ‌static u_char      *ngx_control_addr;
  160. #endif
  161. ‌static char        *ngx_signal;


  162. ‌static char **ngx_os_environ;


  163. int ngx_cdecl
  164. ‌main(int argc, char *const *argv)
  165. {
  166.     ngx_buf_t        *b;
  167.     ngx_log_t        *log;
  168.     ngx_uint_t        i;
  169.     ngx_cycle_t      *cycle, init_cycle;
  170.     ngx_conf_dump_t  *cd;
  171.     ngx_core_conf_t  *ccf;

  172.     ngx_debug_init();

  173.     if (ngx_strerror_init() != NGX_OK) {
  174.         return 1;
  175.     }

  176.     if (ngx_get_options(argc, argv) != NGX_OK) {
  177.         return 1;
  178.     }

  179.     if (ngx_show_version) {
  180.         ngx_show_version_info();

  181.         if (!ngx_test_config) {
  182.             return 0;
  183.         }
  184.     }

  185.     /* TODO */ ngx_max_sockets = -1;

  186.     ngx_time_init();

  187. #if (NGX_PCRE)
  188.     ngx_regex_init();
  189. #endif

  190.     ngx_pid = ngx_getpid();
  191.     ngx_parent = ngx_getppid();

  192.     log = ngx_log_init(ngx_prefix, ngx_error_log);
  193.     if (log == NULL) {
  194.         return 1;
  195.     }

  196.     /* STUB */
  197. #if (NGX_OPENSSL)
  198.     ngx_ssl_init(log);
  199. #endif

  200.     /*
  201.      * init_cycle->log is required for signal handlers and
  202.      * ngx_process_options()
  203.      */

  204.     ngx_memzero(&init_cycle, sizeof(ngx_cycle_t));
  205.     init_cycle.log = log;
  206.     ngx_cycle = &init_cycle;

  207.     init_cycle.pool = ngx_create_pool(1024, log);
  208.     if (init_cycle.pool == NULL) {
  209.         return 1;
  210.     }

  211.     if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) {
  212.         return 1;
  213.     }

  214.     if (ngx_process_options(&init_cycle) != NGX_OK) {
  215.         return 1;
  216.     }

  217.     if (ngx_os_init(log) != NGX_OK) {
  218.         return 1;
  219.     }

  220.     /*
  221.      * ngx_crc32_table_init() requires ngx_cacheline_size set in ngx_os_init()
  222.      */

  223.     if (ngx_crc32_table_init() != NGX_OK) {
  224.         return 1;
  225.     }

  226.     /*
  227.      * ngx_slab_sizes_init() requires ngx_pagesize set in ngx_os_init()
  228.      */

  229.     ngx_slab_sizes_init();

  230.     if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {
  231.         return 1;
  232.     }

  233. #if (NGX_CONTROL_API)
  234.     ngx_control_preinit();
  235. #endif

  236.     if (ngx_preinit_modules() != NGX_OK) {
  237.         return 1;
  238.     }

  239.     cycle = ngx_init_cycle(&init_cycle);
  240.     if (cycle == NULL) {
  241.         if (ngx_test_config) {
  242.             ngx_log_stderr(0, "configuration file %s test failed",
  243.                            init_cycle.conf_file.data);
  244.         }

  245.         return 1;
  246.     }

  247.     if (ngx_test_config) {
  248.         if (!ngx_quiet_mode) {
  249.             ngx_log_stderr(0, "configuration file %s test is successful",
  250.                            cycle->conf_file.data);
  251.         }

  252.         if (ngx_dump_config) {
  253.             cd = cycle->config_dump.elts;

  254.             for (i = 0; i < cycle->config_dump.nelts; i++) {

  255.                 ngx_write_stdout("# configuration file ");
  256.                 (void) ngx_write_fd(ngx_stdout, cd[i].name.data,
  257.                                     cd[i].name.len);
  258.                 ngx_write_stdout(":" NGX_LINEFEED);

  259.                 b = cd[i].buffer;

  260.                 (void) ngx_write_fd(ngx_stdout, b->pos, b->last - b->pos);
  261.                 ngx_write_stdout(NGX_LINEFEED);
  262.             }
  263.         }

  264.         return 0;
  265.     }

  266.     if (ngx_signal) {
  267.         return ngx_signal_process(cycle, ngx_signal);
  268.     }

  269.     ngx_os_status(cycle->log);

  270.     ngx_cycle = cycle;

  271.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  272.     if (ccf->master && ngx_process == NGX_PROCESS_SINGLE) {
  273.         ngx_process = NGX_PROCESS_MASTER;
  274.     }

  275. #if !(NGX_WIN32)

  276.     if (ngx_init_signals(cycle->log) != NGX_OK) {
  277.         return 1;
  278.     }

  279.     if (!ngx_inherited && ccf->daemon) {
  280.         if (ngx_daemon(cycle->log) != NGX_OK) {
  281.             return 1;
  282.         }

  283.         ngx_daemonized = 1;
  284.     }

  285.     if (ngx_inherited) {
  286.         ngx_daemonized = 1;
  287.     }

  288. #endif

  289. #if (NGX_CONTROL_API)
  290.     if (ngx_process == NGX_PROCESS_SINGLE) {
  291.         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  292.                       "control API unavailable in single process mode");

  293.     } else {
  294.         if (ngx_control_init(ngx_control_addr) != NGX_OK) {
  295.             return 1;
  296.         }
  297.     }
  298. #endif

  299.     if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) {
  300.         return 1;
  301.     }

  302.     if (ngx_log_redirect_stderr(cycle) != NGX_OK) {
  303.         return 1;
  304.     }

  305.     if (log->file->fd != ngx_stderr) {
  306.         if (ngx_close_file(log->file->fd) == NGX_FILE_ERROR) {
  307.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  308.                           ngx_close_file_n " built-in log failed");
  309.         }
  310.     }

  311.     ngx_use_stderr = 0;

  312.     if (ngx_process == NGX_PROCESS_SINGLE) {
  313.         ngx_single_process_cycle(cycle);

  314.     } else {
  315.         ngx_master_process_cycle(cycle);
  316.     }

  317.     return 0;
  318. }


  319. static void
  320. ‌ngx_show_version_info(void)
  321. {
  322.     ngx_write_stderr("nginx version: " NGINX_VER_BUILD NGX_LINEFEED);

  323.     if (ngx_show_help) {
  324.         ngx_write_stderr(
  325.             "Usage: nginx [-?hvVtTq] [-s signal] [-p prefix]" NGX_LINEFEED
  326.             "             [-e filename] [-c filename] [-g directives]"
  327.                           NGX_LINEFEED NGX_LINEFEED
  328.             "Options:" NGX_LINEFEED
  329.             "  -?,-h         : this help" NGX_LINEFEED
  330.             "  -v            : show version and exit" NGX_LINEFEED
  331.             "  -V            : show version and configure options then exit"
  332.                                NGX_LINEFEED
  333.             "  -t            : test configuration and exit" NGX_LINEFEED
  334.             "  -T            : test configuration, dump it and exit"
  335.                                NGX_LINEFEED
  336.             "  -q            : suppress non-error messages "
  337.                                "during configuration testing" NGX_LINEFEED
  338.             "  -s signal     : send signal to a master process: "
  339.                                "stop, quit, reopen, reload" NGX_LINEFEED
  340. #if (NGX_CONTROL_API)
  341.             "  -l addr       : open control socket on address" NGX_LINEFEED
  342. #endif
  343. #ifdef NGX_PREFIX
  344.             "  -p prefix     : set prefix path (default: " NGX_PREFIX ")"
  345.                                NGX_LINEFEED
  346. #else
  347.             "  -p prefix     : set prefix path (default: NONE)" NGX_LINEFEED
  348. #endif
  349.             "  -e filename   : set error log file (default: "
  350. #ifdef NGX_ERROR_LOG_STDERR
  351.                                "stderr)" NGX_LINEFEED
  352. #else
  353.                                NGX_ERROR_LOG_PATH ")" NGX_LINEFEED
  354. #endif
  355.             "  -c filename   : set configuration file (default: " NGX_CONF_PATH
  356.                                ")" NGX_LINEFEED
  357.             "  -g directives : set global directives out of configuration "
  358.                                "file" NGX_LINEFEED NGX_LINEFEED
  359.         );
  360.     }

  361.     if (ngx_show_configure) {

  362. #ifdef NGX_COMPILER
  363.         ngx_write_stderr("built by " NGX_COMPILER NGX_LINEFEED);
  364. #endif

  365. #if (NGX_SSL)
  366.         if (ngx_strcmp(ngx_ssl_version(), OPENSSL_VERSION_TEXT) == 0) {
  367.             ngx_write_stderr("built with " OPENSSL_VERSION_TEXT NGX_LINEFEED);
  368.         } else {
  369.             ngx_write_stderr("built with " OPENSSL_VERSION_TEXT
  370.                              " (running with ");
  371.             ngx_write_stderr((char *) (uintptr_t) ngx_ssl_version());
  372.             ngx_write_stderr(")" NGX_LINEFEED);
  373.         }
  374. #ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
  375.         ngx_write_stderr("TLS SNI support enabled" NGX_LINEFEED);
  376. #else
  377.         ngx_write_stderr("TLS SNI support disabled" NGX_LINEFEED);
  378. #endif
  379. #endif

  380.         ngx_write_stderr("configure arguments:" NGX_CONFIGURE NGX_LINEFEED);
  381.     }
  382. }


  383. static ngx_int_t
  384. ‌ngx_add_inherited_sockets(ngx_cycle_t *cycle)
  385. {
  386.     u_char           *p, *v, *inherited;
  387.     ngx_int_t         s;
  388.     ngx_listening_t  *ls;

  389.     inherited = (u_char *) getenv(NGINX_VAR);

  390.     if (inherited == NULL) {
  391.         return NGX_OK;
  392.     }

  393.     ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0,
  394.                   "using inherited sockets from \"%s\"", inherited);

  395.     if (ngx_array_init(&cycle->listening, cycle->pool, 10,
  396.                        sizeof(ngx_listening_t))
  397.         != NGX_OK)
  398.     {
  399.         return NGX_ERROR;
  400.     }

  401.     for (p = inherited, v = p; *p; p++) {
  402.         if (*p == ':' || *p == ';') {
  403.             s = ngx_atoi(v, p - v);
  404.             if (s == NGX_ERROR) {
  405.                 ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  406.                               "invalid socket number \"%s\" in " NGINX_VAR
  407.                               " environment variable, ignoring the rest"
  408.                               " of the variable", v);
  409.                 break;
  410.             }

  411.             v = p + 1;

  412.             ls = ngx_array_push(&cycle->listening);
  413.             if (ls == NULL) {
  414.                 return NGX_ERROR;
  415.             }

  416.             ngx_memzero(ls, sizeof(ngx_listening_t));

  417.             ls->fd = (ngx_socket_t) s;
  418.             ls->inherited = 1;
  419.         }
  420.     }

  421.     if (v != p) {
  422.         ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  423.                       "invalid socket number \"%s\" in " NGINX_VAR
  424.                       " environment variable, ignoring", v);
  425.     }

  426.     ngx_inherited = 1;

  427.     return ngx_set_inherited_sockets(cycle);
  428. }


  429. char **
  430. ‌ngx_set_environment(ngx_cycle_t *cycle, ngx_uint_t *last)
  431. {
  432.     char                **p, **env, *str;
  433.     size_t                len;
  434.     ngx_str_t            *var;
  435.     ngx_uint_t            i, n;
  436.     ngx_core_conf_t      *ccf;
  437.     ngx_pool_cleanup_t   *cln;

  438.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  439.     if (last == NULL && ccf->environment) {
  440.         return ccf->environment;
  441.     }

  442.     var = ccf->env.elts;

  443.     for (i = 0; i < ccf->env.nelts; i++) {
  444.         if (ngx_strcmp(var[i].data, "TZ") == 0
  445.             || ngx_strncmp(var[i].data, "TZ=", 3) == 0)
  446.         {
  447.             goto tz_found;
  448.         }
  449.     }

  450.     var = ngx_array_push(&ccf->env);
  451.     if (var == NULL) {
  452.         return NULL;
  453.     }

  454.     var->len = 2;
  455.     var->data = (u_char *) "TZ";

  456.     var = ccf->env.elts;

  457. tz_found:

  458.     n = 0;

  459.     for (i = 0; i < ccf->env.nelts; i++) {

  460.         if (var[i].data[var[i].len] == '=') {
  461.             n++;
  462.             continue;
  463.         }

  464.         for (p = ngx_os_environ; *p; p++) {

  465.             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
  466.                 && (*p)[var[i].len] == '=')
  467.             {
  468.                 n++;
  469.                 break;
  470.             }
  471.         }
  472.     }

  473.     if (last) {
  474.         env = ngx_alloc((*last + n + 1) * sizeof(char *), cycle->log);
  475.         if (env == NULL) {
  476.             return NULL;
  477.         }

  478.         *last = n;

  479.     } else {
  480.         cln = ngx_pool_cleanup_add(cycle->pool, 0);
  481.         if (cln == NULL) {
  482.             return NULL;
  483.         }

  484.         env = ngx_alloc((n + 1) * sizeof(char *), cycle->log);
  485.         if (env == NULL) {
  486.             return NULL;
  487.         }

  488.         cln->handler = ngx_cleanup_environment;
  489.         cln->data = env;
  490.     }

  491.     n = 0;

  492.     for (i = 0; i < ccf->env.nelts; i++) {

  493.         if (var[i].data[var[i].len] == '=') {

  494.             if (last) {
  495.                 env[n++] = (char *) var[i].data;
  496.                 continue;
  497.             }

  498.             cln = ngx_pool_cleanup_add(cycle->pool, 0);
  499.             if (cln == NULL) {
  500.                 return NULL;
  501.             }

  502.             len = ngx_strlen(var[i].data) + 1;

  503.             str = ngx_alloc(len, cycle->log);
  504.             if (str == NULL) {
  505.                 return NULL;
  506.             }

  507.             ngx_memcpy(str, var[i].data, len);

  508.             cln->handler = ngx_cleanup_environment_variable;
  509.             cln->data = str;

  510.             env[n++] = str;

  511.             continue;
  512.         }

  513.         for (p = ngx_os_environ; *p; p++) {

  514.             if (ngx_strncmp(*p, var[i].data, var[i].len) == 0
  515.                 && (*p)[var[i].len] == '=')
  516.             {
  517.                 env[n++] = *p;
  518.                 break;
  519.             }
  520.         }
  521.     }

  522.     env[n] = NULL;

  523.     if (last == NULL) {
  524.         ccf->environment = env;
  525.         environ = env;
  526.     }

  527.     return env;
  528. }


  529. static void
  530. ‌ngx_cleanup_environment(void *data)
  531. {
  532.     char  **env = data;

  533.     if (environ == env) {

  534.         /*
  535.          * if the environment is still used, as it happens on exit,
  536.          * the only option is to leak it
  537.          */

  538.         return;
  539.     }

  540.     ngx_free(env);
  541. }


  542. static void
  543. ‌ngx_cleanup_environment_variable(void *data)
  544. {
  545.     char  *var = data;

  546.     char  **p;

  547.     for (p = environ; *p; p++) {

  548.         /*
  549.          * if an environment variable is still used, as it happens on exit,
  550.          * the only option is to leak it
  551.          */

  552.         if (*p == var) {
  553.             return;
  554.         }
  555.     }

  556.     ngx_free(var);
  557. }


  558. ngx_pid_t
  559. ‌ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv)
  560. {
  561.     char             **env, *var;
  562.     u_char            *p;
  563.     ngx_uint_t         i, n;
  564.     ngx_pid_t          pid;
  565.     ngx_exec_ctx_t     ctx;
  566.     ngx_core_conf_t   *ccf;
  567.     ngx_listening_t   *ls;

  568.     ngx_memzero(&ctx, sizeof(ngx_exec_ctx_t));

  569.     ctx.path = argv[0];
  570.     ctx.name = "new binary process";
  571.     ctx.argv = argv;

  572.     n = 3;
  573.     env = ngx_set_environment(cycle, &n);
  574.     if (env == NULL) {
  575.         return NGX_INVALID_PID;
  576.     }

  577.     var = ngx_alloc(sizeof(NGINX_VAR)
  578.                     + cycle->listening.nelts * (NGX_INT32_LEN + 1) + 2,
  579.                     cycle->log);
  580.     if (var == NULL) {
  581.         ngx_free(env);
  582.         return NGX_INVALID_PID;
  583.     }

  584.     p = ngx_cpymem(var, NGINX_VAR "=", sizeof(NGINX_VAR));

  585.     ls = cycle->listening.elts;
  586.     for (i = 0; i < cycle->listening.nelts; i++) {
  587.         if (ls[i].ignore) {
  588.             continue;
  589.         }
  590.         p = ngx_sprintf(p, "%ud;", ls[i].fd);
  591.     }

  592.     *p = '\0';

  593.     env[n++] = var;

  594. #if (NGX_SETPROCTITLE_USES_ENV)

  595.     /* allocate the spare 300 bytes for the new binary process title */

  596.     env[n++] = "SPARE=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  597.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  598.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  599.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
  600.                "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

  601. #endif

  602. #if (NGX_CONTROL_API)
  603.     env[n] = ngx_control_handoff();

  604.     if (env[n] != NULL) {
  605.         n++;
  606.     }
  607. #endif

  608.     env[n] = NULL;

  609. #if (NGX_DEBUG)
  610.     {
  611.     char  **e;
  612.     for (e = env; *e; e++) {
  613.         ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "env: %s", *e);
  614.     }
  615.     }
  616. #endif

  617.     ctx.envp = (char *const *) env;

  618.     ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);

  619.     if (ngx_rename_file(ccf->pid.data, ccf->oldpid.data) == NGX_FILE_ERROR) {
  620.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  621.                       ngx_rename_file_n " %s to %s failed "
  622.                       "before executing new binary process \"%s\"",
  623.                       ccf->pid.data, ccf->oldpid.data, argv[0]);

  624.         ngx_free(env);
  625.         ngx_free(var);

  626.         return NGX_INVALID_PID;
  627.     }

  628.     pid = ngx_execute(cycle, &ctx);

  629.     if (pid == NGX_INVALID_PID) {
  630.         if (ngx_rename_file(ccf->oldpid.data, ccf->pid.data)
  631.             == NGX_FILE_ERROR)
  632.         {
  633.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  634.                           ngx_rename_file_n " %s back to %s failed after "
  635.                           "an attempt to execute new binary process \"%s\"",
  636.                           ccf->oldpid.data, ccf->pid.data, argv[0]);
  637.         }
  638.     }

  639.     ngx_free(env);
  640.     ngx_free(var);

  641.     return pid;
  642. }


  643. static ngx_int_t
  644. ‌ngx_get_options(int argc, char *const *argv)
  645. {
  646.     u_char     *p;
  647.     ngx_int_t   i;

  648.     for (i = 1; i < argc; i++) {

  649.         p = (u_char *) argv[i];

  650.         if (*p++ != '-') {
  651.             ngx_log_stderr(0, "invalid option: \"%s\"", argv[i]);
  652.             return NGX_ERROR;
  653.         }

  654.         while (*p) {

  655.             switch (*p++) {

  656.             case '?':
  657.             case 'h':
  658.                 ngx_show_version = 1;
  659.                 ngx_show_help = 1;
  660.                 break;

  661.             case 'v':
  662.                 ngx_show_version = 1;
  663.                 break;

  664.             case 'V':
  665.                 ngx_show_version = 1;
  666.                 ngx_show_configure = 1;
  667.                 break;

  668.             case 't':
  669.                 ngx_test_config = 1;
  670.                 break;

  671.             case 'T':
  672.                 ngx_test_config = 1;
  673.                 ngx_dump_config = 1;
  674.                 break;

  675.             case 'q':
  676.                 ngx_quiet_mode = 1;
  677.                 break;

  678.             case 'p':
  679.                 if (*p) {
  680.                     ngx_prefix = p;
  681.                     goto next;
  682.                 }

  683.                 if (argv[++i]) {
  684.                     ngx_prefix = (u_char *) argv[i];
  685.                     goto next;
  686.                 }

  687.                 ngx_log_stderr(0, "option \"-p\" requires directory name");
  688.                 return NGX_ERROR;

  689.             case 'e':
  690.                 if (*p) {
  691.                     ngx_error_log = p;

  692.                 } else if (argv[++i]) {
  693.                     ngx_error_log = (u_char *) argv[i];

  694.                 } else {
  695.                     ngx_log_stderr(0, "option \"-e\" requires file name");
  696.                     return NGX_ERROR;
  697.                 }

  698.                 if (ngx_strcmp(ngx_error_log, "stderr") == 0) {
  699.                     ngx_error_log = (u_char *) "";
  700.                 }

  701.                 goto next;

  702.             case 'c':
  703.                 if (*p) {
  704.                     ngx_conf_file = p;
  705.                     goto next;
  706.                 }

  707.                 if (argv[++i]) {
  708.                     ngx_conf_file = (u_char *) argv[i];
  709.                     goto next;
  710.                 }

  711.                 ngx_log_stderr(0, "option \"-c\" requires file name");
  712.                 return NGX_ERROR;

  713.             case 'g':
  714.                 if (*p) {
  715.                     ngx_conf_params = p;
  716.                     goto next;
  717.                 }

  718.                 if (argv[++i]) {
  719.                     ngx_conf_params = (u_char *) argv[i];
  720.                     goto next;
  721.                 }

  722.                 ngx_log_stderr(0, "option \"-g\" requires parameter");
  723.                 return NGX_ERROR;

  724.             case 's':
  725.                 if (*p) {
  726.                     ngx_signal = (char *) p;

  727.                 } else if (argv[++i]) {
  728.                     ngx_signal = argv[i];

  729.                 } else {
  730.                     ngx_log_stderr(0, "option \"-s\" requires parameter");
  731.                     return NGX_ERROR;
  732.                 }

  733.                 if (ngx_strcmp(ngx_signal, "stop") == 0
  734.                     || ngx_strcmp(ngx_signal, "quit") == 0
  735.                     || ngx_strcmp(ngx_signal, "reopen") == 0
  736.                     || ngx_strcmp(ngx_signal, "reload") == 0)
  737.                 {
  738.                     ngx_process = NGX_PROCESS_SIGNALLER;
  739.                     goto next;
  740.                 }

  741.                 ngx_log_stderr(0, "invalid option: \"-s %s\"", ngx_signal);
  742.                 return NGX_ERROR;

  743. #if (NGX_CONTROL_API)
  744.             case 'l':
  745.                 ngx_control_api_enabled = 1;

  746.                 if (*p) {
  747.                     ngx_control_addr = p;
  748.                     goto next;
  749.                 }

  750.                 if (argv[++i]) {
  751.                     ngx_control_addr = (u_char *) argv[i];
  752.                     goto next;
  753.                 }

  754.                 ngx_log_stderr(0, "option \"-l\" requires listen address");
  755.                 return NGX_ERROR;
  756. #endif

  757.             default:
  758.                 ngx_log_stderr(0, "invalid option: \"%c\"", *(p - 1));
  759.                 return NGX_ERROR;
  760.             }
  761.         }

  762.     next:

  763.         continue;
  764.     }

  765.     return NGX_OK;
  766. }


  767. static ngx_int_t
  768. ‌ngx_save_argv(ngx_cycle_t *cycle, int argc, char *const *argv)
  769. {
  770. #if (NGX_FREEBSD)

  771.     ngx_os_argv = (char **) argv;
  772.     ngx_argc = argc;
  773.     ngx_argv = (char **) argv;

  774. #else
  775.     size_t     len;
  776.     ngx_int_t  i;

  777.     ngx_os_argv = (char **) argv;
  778.     ngx_argc = argc;

  779.     ngx_argv = ngx_alloc((argc + 1) * sizeof(char *), cycle->log);
  780.     if (ngx_argv == NULL) {
  781.         return NGX_ERROR;
  782.     }

  783.     for (i = 0; i < argc; i++) {
  784.         len = ngx_strlen(argv[i]) + 1;

  785.         ngx_argv[i] = ngx_alloc(len, cycle->log);
  786.         if (ngx_argv[i] == NULL) {
  787.             return NGX_ERROR;
  788.         }

  789.         (void) ngx_cpystrn((u_char *) ngx_argv[i], (u_char *) argv[i], len);
  790.     }

  791.     ngx_argv[i] = NULL;

  792. #endif

  793.     ngx_os_environ = environ;

  794.     return NGX_OK;
  795. }


  796. static ngx_int_t
  797. ‌ngx_process_options(ngx_cycle_t *cycle)
  798. {
  799.     u_char  *p;
  800.     size_t   len;

  801.     if (ngx_prefix) {
  802.         len = ngx_strlen(ngx_prefix);
  803.         p = ngx_prefix;

  804.         if (len && !ngx_path_separator(p[len - 1])) {
  805.             p = ngx_pnalloc(cycle->pool, len + 1);
  806.             if (p == NULL) {
  807.                 return NGX_ERROR;
  808.             }

  809.             ngx_memcpy(p, ngx_prefix, len);
  810.             p[len++] = '/';
  811.         }

  812.         cycle->conf_prefix.len = len;
  813.         cycle->conf_prefix.data = p;
  814.         cycle->prefix.len = len;
  815.         cycle->prefix.data = p;

  816.     } else {

  817. #ifndef NGX_PREFIX

  818.         p = ngx_pnalloc(cycle->pool, NGX_MAX_PATH);
  819.         if (p == NULL) {
  820.             return NGX_ERROR;
  821.         }

  822.         if (ngx_getcwd(p, NGX_MAX_PATH) == 0) {
  823.             ngx_log_stderr(ngx_errno, "[emerg]: " ngx_getcwd_n " failed");
  824.             return NGX_ERROR;
  825.         }

  826.         len = ngx_strlen(p);

  827.         p[len++] = '/';

  828.         cycle->conf_prefix.len = len;
  829.         cycle->conf_prefix.data = p;
  830.         cycle->prefix.len = len;
  831.         cycle->prefix.data = p;

  832. #else

  833. #ifdef NGX_CONF_PREFIX
  834.         ngx_str_set(&cycle->conf_prefix, NGX_CONF_PREFIX);
  835. #else
  836.         ngx_str_set(&cycle->conf_prefix, NGX_PREFIX);
  837. #endif
  838.         ngx_str_set(&cycle->prefix, NGX_PREFIX);

  839. #endif
  840.     }

  841.     if (ngx_conf_file) {
  842.         cycle->conf_file.len = ngx_strlen(ngx_conf_file);
  843.         cycle->conf_file.data = ngx_conf_file;

  844.     } else {
  845.         ngx_str_set(&cycle->conf_file, NGX_CONF_PATH);
  846.     }

  847.     if (ngx_conf_full_name(cycle, &cycle->conf_file, 0) != NGX_OK) {
  848.         return NGX_ERROR;
  849.     }

  850.     for (p = cycle->conf_file.data + cycle->conf_file.len - 1;
  851.          p > cycle->conf_file.data;
  852.          p--)
  853.     {
  854.         if (ngx_path_separator(*p)) {
  855.             cycle->conf_prefix.len = p - cycle->conf_file.data + 1;
  856.             cycle->conf_prefix.data = cycle->conf_file.data;
  857.             break;
  858.         }
  859.     }

  860.     if (ngx_error_log) {
  861.         cycle->error_log.len = ngx_strlen(ngx_error_log);
  862.         cycle->error_log.data = ngx_error_log;

  863.     } else {
  864.         ngx_str_set(&cycle->error_log, NGX_ERROR_LOG_PATH);
  865.     }

  866.     if (ngx_conf_params) {
  867.         cycle->conf_param.len = ngx_strlen(ngx_conf_params);
  868.         cycle->conf_param.data = ngx_conf_params;
  869.     }

  870.     if (ngx_test_config) {
  871.         cycle->log->log_level = NGX_LOG_INFO;
  872.     }

  873.     return NGX_OK;
  874. }


  875. static void *
  876. ‌ngx_core_module_create_conf(ngx_cycle_t *cycle)
  877. {
  878.     ngx_core_conf_t  *ccf;

  879.     ccf = ngx_pcalloc(cycle->pool, sizeof(ngx_core_conf_t));
  880.     if (ccf == NULL) {
  881.         return NULL;
  882.     }

  883.     /*
  884.      * set by ngx_pcalloc()
  885.      *
  886.      *     ccf->pid = NULL;
  887.      *     ccf->oldpid = NULL;
  888.      *     ccf->priority = 0;
  889.      *     ccf->cpu_affinity_auto = 0;
  890.      *     ccf->cpu_affinity_n = 0;
  891.      *     ccf->cpu_affinity = NULL;
  892.      */

  893.     ccf->daemon = NGX_CONF_UNSET;
  894.     ccf->master = NGX_CONF_UNSET;
  895.     ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
  896.     ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC;

  897.     ccf->worker_processes = NGX_CONF_UNSET;
  898.     ccf->debug_points = NGX_CONF_UNSET;

  899.     ccf->rlimit_nofile = NGX_CONF_UNSET;
  900.     ccf->rlimit_core = NGX_CONF_UNSET;

  901.     ccf->user = (ngx_uid_t) NGX_CONF_UNSET_UINT;
  902.     ccf->group = (ngx_gid_t) NGX_CONF_UNSET_UINT;

  903.     if (ngx_array_init(&ccf->env, cycle->pool, 1, sizeof(ngx_str_t))
  904.         != NGX_OK)
  905.     {
  906.         return NULL;
  907.     }

  908.     return ccf;
  909. }


  910. static char *
  911. ‌ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
  912. {
  913.     ngx_core_conf_t  *ccf = conf;

  914.     ngx_conf_init_value(ccf->daemon, 1);
  915.     ngx_conf_init_value(ccf->master, 1);
  916.     ngx_conf_init_msec_value(ccf->timer_resolution, 0);
  917.     ngx_conf_init_msec_value(ccf->shutdown_timeout, 0);

  918.     ngx_conf_init_value(ccf->worker_processes, 1);
  919.     ngx_conf_init_value(ccf->debug_points, 0);

  920. #if (NGX_HAVE_CPU_AFFINITY)

  921.     if (!ccf->cpu_affinity_auto
  922.         && ccf->cpu_affinity_n
  923.         && ccf->cpu_affinity_n != 1
  924.         && ccf->cpu_affinity_n != (ngx_uint_t) ccf->worker_processes)
  925.     {
  926.         ngx_log_error(NGX_LOG_WARN, cycle->log, 0,
  927.                       "the number of \"worker_processes\" is not equal to "
  928.                       "the number of \"worker_cpu_affinity\" masks, "
  929.                       "using last mask for remaining worker processes");
  930.     }

  931. #endif


  932.     if (ccf->pid.len == 0) {
  933.         ngx_str_set(&ccf->pid, NGX_PID_PATH);
  934.     }

  935.     if (ngx_conf_full_name(cycle, &ccf->pid, 0) != NGX_OK) {
  936.         return NGX_CONF_ERROR;
  937.     }

  938.     ccf->oldpid.len = ccf->pid.len + sizeof(NGX_OLDPID_EXT);

  939.     ccf->oldpid.data = ngx_pnalloc(cycle->pool, ccf->oldpid.len);
  940.     if (ccf->oldpid.data == NULL) {
  941.         return NGX_CONF_ERROR;
  942.     }

  943.     ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len),
  944.                NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT));


  945. #if !(NGX_WIN32)

  946.     if (ccf->user == (uid_t) NGX_CONF_UNSET_UINT && geteuid() == 0) {
  947.         struct group   *grp;
  948.         struct passwd  *pwd;

  949.         ngx_set_errno(0);
  950.         pwd = getpwnam(NGX_USER);
  951.         if (pwd == NULL) {
  952.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  953.                           "getpwnam(\"" NGX_USER "\") failed");
  954.             return NGX_CONF_ERROR;
  955.         }

  956.         ccf->username = NGX_USER;
  957.         ccf->user = pwd->pw_uid;

  958.         ngx_set_errno(0);
  959.         grp = getgrnam(NGX_GROUP);
  960.         if (grp == NULL) {
  961.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  962.                           "getgrnam(\"" NGX_GROUP "\") failed");
  963.             return NGX_CONF_ERROR;
  964.         }

  965.         ccf->group = grp->gr_gid;
  966.     }


  967.     if (ccf->lock_file.len == 0) {
  968.         ngx_str_set(&ccf->lock_file, NGX_LOCK_PATH);
  969.     }

  970.     if (ngx_conf_full_name(cycle, &ccf->lock_file, 0) != NGX_OK) {
  971.         return NGX_CONF_ERROR;
  972.     }

  973.     {
  974.     ngx_str_t  lock_file;

  975.     lock_file = cycle->old_cycle->lock_file;

  976.     if (lock_file.len) {
  977.         lock_file.len--;

  978.         if (ccf->lock_file.len != lock_file.len
  979.             || ngx_strncmp(ccf->lock_file.data, lock_file.data, lock_file.len)
  980.                != 0)
  981.         {
  982.             ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
  983.                           "\"lock_file\" could not be changed, ignored");
  984.         }

  985.         cycle->lock_file.len = lock_file.len + 1;
  986.         lock_file.len += sizeof(".accept");

  987.         cycle->lock_file.data = ngx_pstrdup(cycle->pool, &lock_file);
  988.         if (cycle->lock_file.data == NULL) {
  989.             return NGX_CONF_ERROR;
  990.         }

  991.     } else {
  992.         cycle->lock_file.len = ccf->lock_file.len + 1;
  993.         cycle->lock_file.data = ngx_pnalloc(cycle->pool,
  994.                                       ccf->lock_file.len + sizeof(".accept"));
  995.         if (cycle->lock_file.data == NULL) {
  996.             return NGX_CONF_ERROR;
  997.         }

  998.         ngx_memcpy(ngx_cpymem(cycle->lock_file.data, ccf->lock_file.data,
  999.                               ccf->lock_file.len),
  1000.                    ".accept", sizeof(".accept"));
  1001.     }
  1002.     }

  1003. #endif

  1004.     return NGX_CONF_OK;
  1005. }


  1006. static char *
  1007. ‌ngx_set_user(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1008. {
  1009. #if (NGX_WIN32)

  1010.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1011.                        "\"user\" is not supported, ignored");

  1012.     return NGX_CONF_OK;

  1013. #else

  1014.     ngx_core_conf_t  *ccf = conf;

  1015.     char             *group;
  1016.     struct passwd    *pwd;
  1017.     struct group     *grp;
  1018.     ngx_str_t        *value;

  1019.     if (ccf->user != (uid_t) NGX_CONF_UNSET_UINT) {
  1020.         return "is duplicate";
  1021.     }

  1022.     if (geteuid() != 0) {
  1023.         ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1024.                            "the \"user\" directive makes sense only "
  1025.                            "if the master process runs "
  1026.                            "with super-user privileges, ignored");
  1027.         return NGX_CONF_OK;
  1028.     }

  1029.     value = cf->args->elts;

  1030.     ccf->username = (char *) value[1].data;

  1031.     ngx_set_errno(0);
  1032.     pwd = getpwnam((const char *) value[1].data);
  1033.     if (pwd == NULL) {
  1034.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  1035.                            "getpwnam(\"%s\") failed", value[1].data);
  1036.         return NGX_CONF_ERROR;
  1037.     }

  1038.     ccf->user = pwd->pw_uid;

  1039.     group = (char *) ((cf->args->nelts == 2) ? value[1].data : value[2].data);

  1040.     ngx_set_errno(0);
  1041.     grp = getgrnam(group);
  1042.     if (grp == NULL) {
  1043.         ngx_conf_log_error(NGX_LOG_EMERG, cf, ngx_errno,
  1044.                            "getgrnam(\"%s\") failed", group);
  1045.         return NGX_CONF_ERROR;
  1046.     }

  1047.     ccf->group = grp->gr_gid;

  1048.     return NGX_CONF_OK;

  1049. #endif
  1050. }


  1051. static char *
  1052. ‌ngx_set_env(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1053. {
  1054.     ngx_core_conf_t  *ccf = conf;

  1055.     ngx_str_t   *value, *var;
  1056.     ngx_uint_t   i;

  1057.     var = ngx_array_push(&ccf->env);
  1058.     if (var == NULL) {
  1059.         return NGX_CONF_ERROR;
  1060.     }

  1061.     value = cf->args->elts;
  1062.     *var = value[1];

  1063.     for (i = 0; i < value[1].len; i++) {

  1064.         if (value[1].data[i] == '=') {

  1065.             var->len = i;

  1066.             return NGX_CONF_OK;
  1067.         }
  1068.     }

  1069.     return NGX_CONF_OK;
  1070. }


  1071. static char *
  1072. ‌ngx_set_priority(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1073. {
  1074.     ngx_core_conf_t  *ccf = conf;

  1075.     ngx_str_t        *value;
  1076.     ngx_uint_t        n, minus;

  1077.     if (ccf->priority != 0) {
  1078.         return "is duplicate";
  1079.     }

  1080.     value = cf->args->elts;

  1081.     if (value[1].data[0] == '-') {
  1082.         n = 1;
  1083.         minus = 1;

  1084.     } else if (value[1].data[0] == '+') {
  1085.         n = 1;
  1086.         minus = 0;

  1087.     } else {
  1088.         n = 0;
  1089.         minus = 0;
  1090.     }

  1091.     ccf->priority = ngx_atoi(&value[1].data[n], value[1].len - n);
  1092.     if (ccf->priority == NGX_ERROR) {
  1093.         return "invalid number";
  1094.     }

  1095.     if (minus) {
  1096.         ccf->priority = -ccf->priority;
  1097.     }

  1098.     return NGX_CONF_OK;
  1099. }


  1100. static char *
  1101. ‌ngx_set_cpu_affinity(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1102. {
  1103. #if (NGX_HAVE_CPU_AFFINITY)
  1104.     ngx_core_conf_t  *ccf = conf;

  1105.     u_char            ch, *p;
  1106.     ngx_str_t        *value;
  1107.     ngx_uint_t        i, n;
  1108.     ngx_cpuset_t     *mask;

  1109.     if (ccf->cpu_affinity) {
  1110.         return "is duplicate";
  1111.     }

  1112.     mask = ngx_palloc(cf->pool, (cf->args->nelts - 1) * sizeof(ngx_cpuset_t));
  1113.     if (mask == NULL) {
  1114.         return NGX_CONF_ERROR;
  1115.     }

  1116.     ccf->cpu_affinity_n = cf->args->nelts - 1;
  1117.     ccf->cpu_affinity = mask;

  1118.     value = cf->args->elts;

  1119.     if (ngx_strcmp(value[1].data, "auto") == 0) {

  1120.         if (cf->args->nelts > 3) {
  1121.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1122.                                "invalid number of arguments in "
  1123.                                "\"worker_cpu_affinity\" directive");
  1124.             return NGX_CONF_ERROR;
  1125.         }

  1126.         ccf->cpu_affinity_auto = 1;

  1127.         CPU_ZERO(&mask[0]);
  1128.         for (i = 0; i < (ngx_uint_t) ngx_min(ngx_ncpu, CPU_SETSIZE); i++) {
  1129.             CPU_SET(i, &mask[0]);
  1130.         }

  1131.         n = 2;

  1132.     } else {
  1133.         n = 1;
  1134.     }

  1135.     for ( /* void */ ; n < cf->args->nelts; n++) {

  1136.         if (value[n].len > CPU_SETSIZE) {
  1137.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1138.                          "\"worker_cpu_affinity\" supports up to %d CPUs only",
  1139.                          CPU_SETSIZE);
  1140.             return NGX_CONF_ERROR;
  1141.         }

  1142.         i = 0;
  1143.         CPU_ZERO(&mask[n - 1]);

  1144.         for (p = value[n].data + value[n].len - 1;
  1145.              p >= value[n].data;
  1146.              p--)
  1147.         {
  1148.             ch = *p;

  1149.             if (ch == ' ') {
  1150.                 continue;
  1151.             }

  1152.             i++;

  1153.             if (ch == '0') {
  1154.                 continue;
  1155.             }

  1156.             if (ch == '1') {
  1157.                 CPU_SET(i - 1, &mask[n - 1]);
  1158.                 continue;
  1159.             }

  1160.             ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1161.                           "invalid character \"%c\" in \"worker_cpu_affinity\"",
  1162.                           ch);
  1163.             return NGX_CONF_ERROR;
  1164.         }
  1165.     }

  1166. #else

  1167.     ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
  1168.                        "\"worker_cpu_affinity\" is not supported "
  1169.                        "on this platform, ignored");
  1170. #endif

  1171.     return NGX_CONF_OK;
  1172. }


  1173. ngx_cpuset_t *
  1174. ‌ngx_get_cpu_affinity(ngx_uint_t n)
  1175. {
  1176. #if (NGX_HAVE_CPU_AFFINITY)
  1177.     ngx_uint_t        i, j;
  1178.     ngx_cpuset_t     *mask;
  1179.     ngx_core_conf_t  *ccf;

  1180.     static ngx_cpuset_t  result;

  1181.     ccf = (ngx_core_conf_t *) ngx_get_conf(ngx_cycle->conf_ctx,
  1182.                                            ngx_core_module);

  1183.     if (ccf->cpu_affinity == NULL) {
  1184.         return NULL;
  1185.     }

  1186.     if (ccf->cpu_affinity_auto) {
  1187.         mask = &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];

  1188.         for (i = 0, j = n; /* void */ ; i++) {

  1189.             if (CPU_ISSET(i % CPU_SETSIZE, mask) && j-- == 0) {
  1190.                 break;
  1191.             }

  1192.             if (i == CPU_SETSIZE && j == n) {
  1193.                 /* empty mask */
  1194.                 return NULL;
  1195.             }

  1196.             /* void */
  1197.         }

  1198.         CPU_ZERO(&result);
  1199.         CPU_SET(i % CPU_SETSIZE, &result);

  1200.         return &result;
  1201.     }

  1202.     if (ccf->cpu_affinity_n > n) {
  1203.         return &ccf->cpu_affinity[n];
  1204.     }

  1205.     return &ccf->cpu_affinity[ccf->cpu_affinity_n - 1];

  1206. #else

  1207.     return NULL;

  1208. #endif
  1209. }


  1210. static char *
  1211. ‌ngx_set_worker_processes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1212. {
  1213.     ngx_str_t        *value;
  1214.     ngx_core_conf_t  *ccf;

  1215.     ccf = (ngx_core_conf_t *) conf;

  1216.     if (ccf->worker_processes != NGX_CONF_UNSET) {
  1217.         return "is duplicate";
  1218.     }

  1219.     value = cf->args->elts;

  1220.     if (ngx_strcmp(value[1].data, "auto") == 0) {
  1221.         ccf->worker_processes = ngx_ncpu;
  1222.         return NGX_CONF_OK;
  1223.     }

  1224.     ccf->worker_processes = ngx_atoi(value[1].data, value[1].len);

  1225.     if (ccf->worker_processes == NGX_ERROR) {
  1226.         return "invalid value";
  1227.     }

  1228.     return NGX_CONF_OK;
  1229. }


  1230. static char *
  1231. ‌ngx_load_module(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  1232. {
  1233. #if (NGX_HAVE_DLOPEN)
  1234.     void                *handle;
  1235.     char               **names, **order;
  1236.     ngx_str_t           *value, file;
  1237.     ngx_uint_t           i;
  1238.     ngx_module_t        *module, **modules;
  1239.     ngx_pool_cleanup_t  *cln;

  1240.     if (cf->cycle->modules_used) {
  1241.         return "is specified too late";
  1242.     }

  1243.     value = cf->args->elts;

  1244.     file = value[1];

  1245.     if (ngx_conf_full_name(cf->cycle, &file, 0) != NGX_OK) {
  1246.         return NGX_CONF_ERROR;
  1247.     }

  1248.     cln = ngx_pool_cleanup_add(cf->cycle->pool, 0);
  1249.     if (cln == NULL) {
  1250.         return NGX_CONF_ERROR;
  1251.     }

  1252.     handle = ngx_dlopen(file.data);
  1253.     if (handle == NULL) {
  1254.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1255.                            ngx_dlopen_n " \"%s\" failed (%s)",
  1256.                            file.data, ngx_dlerror());
  1257.         return NGX_CONF_ERROR;
  1258.     }

  1259.     cln->handler = ngx_unload_module;
  1260.     cln->data = handle;

  1261.     modules = ngx_dlsym(handle, "ngx_modules");
  1262.     if (modules == NULL) {
  1263.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1264.                            ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
  1265.                            &value[1], "ngx_modules", ngx_dlerror());
  1266.         return NGX_CONF_ERROR;
  1267.     }

  1268.     names = ngx_dlsym(handle, "ngx_module_names");
  1269.     if (names == NULL) {
  1270.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1271.                            ngx_dlsym_n " \"%V\", \"%s\" failed (%s)",
  1272.                            &value[1], "ngx_module_names", ngx_dlerror());
  1273.         return NGX_CONF_ERROR;
  1274.     }

  1275.     order = ngx_dlsym(handle, "ngx_module_order");

  1276.     for (i = 0; modules[i]; i++) {
  1277.         module = modules[i];
  1278.         module->name = names[i];

  1279.         if (ngx_add_module(cf, &file, module, order) != NGX_OK) {
  1280.             return NGX_CONF_ERROR;
  1281.         }

  1282.         ngx_log_debug2(NGX_LOG_DEBUG_CORE, cf->log, 0, "module: %s i:%ui",
  1283.                        module->name, module->index);
  1284.     }

  1285.     return NGX_CONF_OK;

  1286. #else

  1287.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  1288.                        "\"load_module\" is not supported "
  1289.                        "on this platform");
  1290.     return NGX_CONF_ERROR;

  1291. #endif
  1292. }


  1293. #if (NGX_HAVE_DLOPEN)

  1294. static void
  1295. ‌ngx_unload_module(void *data)
  1296. {
  1297.     void  *handle = data;

  1298.     if (ngx_dlclose(handle) != 0) {
  1299.         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
  1300.                       ngx_dlclose_n " failed (%s)", ngx_dlerror());
  1301.     }
  1302. }

  1303. #endif