int fpm_unix_init_main() /* {{{ */ { struct fpm_worker_pool_s *wp; fpm_pagesize = getpagesize(); if (fpm_global_config.daemonize) { switch (fork()) { case -1 : zlog(ZLOG_STUFF, ZLOG_SYSERROR, "daemonized fork() failed"); return -1; case 0 : break; default : fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT); exit(0); } } setsid(); if (0 > fpm_clock_init()) { return -1; } fpm_globals.parent_pid = getpid(); for (wp = fpm_worker_all_pools; wp; wp = wp->next) { if (0 > fpm_unix_conf_wp(wp)) { return -1; } } fpm_stdio_init_final(); return 0; }
int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { int is_root = !geteuid(); int made_chroot = 0; if (wp->config->rlimit_files) { struct rlimit r; r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files; if (0 > setrlimit(RLIMIT_NOFILE, &r)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setrlimit(RLIMIT_NOFILE, %d) failed (%d)", wp->config->name, wp->config->rlimit_files, errno); } } if (wp->config->rlimit_core) { struct rlimit r; r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core; if (0 > setrlimit(RLIMIT_CORE, &r)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setrlimit(RLIMIT_CORE, %d) failed (%d)", wp->config->name, wp->config->rlimit_core, errno); } } if (is_root && wp->config->chroot && *wp->config->chroot) { if (0 > chroot(wp->config->chroot)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] chroot(%s) failed", wp->config->name, wp->config->chroot); return -1; } made_chroot = 1; } if (wp->config->chdir && *wp->config->chdir) { if (0 > chdir(wp->config->chdir)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] chdir(%s) failed", wp->config->name, wp->config->chdir); return -1; } } else if (made_chroot) { chdir("/"); } if (is_root) { if (wp->set_gid) { if (0 > setgid(wp->set_gid)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setgid(%d) failed", wp->config->name, wp->set_gid); return -1; } } if (wp->set_uid) { if (0 > initgroups(wp->config->user, wp->set_gid)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] initgroups(%s, %d) failed", wp->config->name, wp->config->user, wp->set_gid); return -1; } if (0 > setuid(wp->set_uid)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] setuid(%d) failed", wp->config->name, wp->set_uid); return -1; } } } #ifdef HAVE_PRCTL if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) { zlog(ZLOG_STUFF, ZLOG_SYSERROR, "[pool %s] prctl(PR_SET_DUMPABLE) failed", wp->config->name); } #endif if (0 > fpm_clock_init()) { return -1; } return 0; }
int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { int is_root = !geteuid(); int made_chroot = 0; if (wp->config->rlimit_files) { struct rlimit r; r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files; if (0 > setrlimit(RLIMIT_NOFILE, &r)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", wp->config->name, wp->config->rlimit_files); } } if (wp->config->rlimit_core) { struct rlimit r; r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core; if (0 > setrlimit(RLIMIT_CORE, &r)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", wp->config->name, wp->config->rlimit_core); } } if (is_root && wp->config->chroot && *wp->config->chroot) { if (0 > chroot(wp->config->chroot)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)", wp->config->name, wp->config->chroot); return -1; } made_chroot = 1; } if (wp->config->chdir && *wp->config->chdir) { if (0 > chdir(wp->config->chdir)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir); return -1; } } else if (made_chroot) { if (0 > chdir("/")) { zlog(ZLOG_WARNING, "[pool %s] failed to chdir(/)", wp->config->name); } } if (is_root) { if (wp->config->process_priority != 64) { if (setpriority(PRIO_PROCESS, 0, wp->config->process_priority) < 0) { zlog(ZLOG_SYSERROR, "[pool %s] Unable to set priority for this new process", wp->config->name); return -1; } } if (wp->set_gid) { if (0 > setgid(wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid); return -1; } } if (wp->set_uid) { if (0 > initgroups(wp->config->user, wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid); return -1; } if (0 > setuid(wp->set_uid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid); return -1; } } } #ifdef HAVE_PRCTL if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name); } #endif if (0 > fpm_clock_init()) { return -1; } #ifdef HAVE_APPARMOR if (wp->config->apparmor_hat) { char *con, *new_con; if (aa_getcon(&con, NULL) == -1) { zlog(ZLOG_SYSERROR, "[pool %s] failed to query apparmor confinement. Please check if \"/proc/*/attr/current\" is read and writeable.", wp->config->name); return -1; } new_con = malloc(strlen(con) + strlen(wp->config->apparmor_hat) + 3); // // + 0 Byte if (!new_con) { zlog(ZLOG_SYSERROR, "[pool %s] failed to allocate memory for apparmor hat change.", wp->config->name); return -1; } if (0 > sprintf(new_con, "%s//%s", con, wp->config->apparmor_hat)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to construct apparmor confinement.", wp->config->name); return -1; } if (0 > aa_change_profile(new_con)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to change to new confinement (%s). Please check if \"/proc/*/attr/current\" is read and writeable and \"change_profile -> %s//*\" is allowed.", wp->config->name, new_con, con); return -1; } free(con); free(new_con); } #endif return 0; }
// 初始化unix int fpm_unix_init_main() /* {{{ */ { struct fpm_worker_pool_s *wp; int is_root = !geteuid(); // 能够打开的最大的文件描述符数量 if (fpm_global_config.rlimit_files) { struct rlimit r; r.rlim_max = r.rlim_cur = (rlim_t) fpm_global_config.rlimit_files; // setrlimit和getrlimit系统调用 if (0 > setrlimit(RLIMIT_NOFILE, &r)) { zlog(ZLOG_SYSERROR, "failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", fpm_global_config.rlimit_files); return -1; } } // coredump的最大值 if (fpm_global_config.rlimit_core) { struct rlimit r; r.rlim_max = r.rlim_cur = fpm_global_config.rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) fpm_global_config.rlimit_core; if (0 > setrlimit(RLIMIT_CORE, &r)) { zlog(ZLOG_SYSERROR, "failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", fpm_global_config.rlimit_core); return -1; } } // linux页面大小 fpm_pagesize = getpagesize(); // 在守护进程模式下,会folk出子进程,而前台进程会当Init完毕后退出程 if (fpm_global_config.daemonize) { /* * If daemonize, the calling process will die soon * and the master process continues to initialize itself. * * The parent process has then to wait for the master * process to initialize to return a consistent exit * value. For this pupose, the master process will * send \"1\" into the pipe if everything went well * and \"0\" otherwise. */ struct timeval tv; fd_set rfds; int ret; // 创建管道,将send_config_pipe两个文件描述符连接起来 if (pipe(fpm_globals.send_config_pipe) == -1) { zlog(ZLOG_SYSERROR, "failed to create pipe"); return -1; } /* then fork */ pid_t pid = fork(); switch (pid) { case -1 : /* error */ zlog(ZLOG_SYSERROR, "failed to daemonize"); return -1; case 0 : /* children */ close(fpm_globals.send_config_pipe[0]); /* close the read side of the pipe */ break; default : /* parent */ close(fpm_globals.send_config_pipe[1]); /* close the write side of the pipe */ /* * wait for 10s before exiting with error * the child is supposed to send 1 or 0 into the pipe to tell the parent * how it goes for it */ FD_ZERO(&rfds); FD_SET(fpm_globals.send_config_pipe[0], &rfds); tv.tv_sec = 10; tv.tv_usec = 0; zlog(ZLOG_DEBUG, "The calling process is waiting for the master process to ping via fd=%d", fpm_globals.send_config_pipe[0]); ret = select(fpm_globals.send_config_pipe[0] + 1, &rfds, NULL, NULL, &tv); if (ret == -1) { zlog(ZLOG_SYSERROR, "failed to select"); exit(FPM_EXIT_SOFTWARE); } if (ret) { /* data available */ int readval; ret = read(fpm_globals.send_config_pipe[0], &readval, sizeof(readval)); if (ret == -1) { zlog(ZLOG_SYSERROR, "failed to read from pipe"); exit(FPM_EXIT_SOFTWARE); } if (ret == 0) { zlog(ZLOG_ERROR, "no data have been read from pipe"); exit(FPM_EXIT_SOFTWARE); } else { // 收到了数据 // 1表示初始化成功 // 0表示失败 if (readval == 1) { zlog(ZLOG_DEBUG, "I received a valid acknoledge from the master process, I can exit without error"); fpm_cleanups_run(FPM_CLEANUP_PARENT_EXIT); exit(FPM_EXIT_OK); } else { zlog(ZLOG_DEBUG, "The master process returned an error !"); exit(FPM_EXIT_SOFTWARE); } } } else { /* no date sent ! */ zlog(ZLOG_ERROR, "the master process didn't send back its status (via the pipe to the calling process)"); exit(FPM_EXIT_SOFTWARE); } exit(FPM_EXIT_SOFTWARE); } } /* continue as a child */ setsid(); if (0 > fpm_clock_init()) { return -1; } // 设置php-fpm进程的优先级 if (fpm_global_config.process_priority != 64) { if (is_root) { if (setpriority(PRIO_PROCESS, 0, fpm_global_config.process_priority) < 0) { zlog(ZLOG_SYSERROR, "Unable to set priority for the master process"); return -1; } } else { zlog(ZLOG_NOTICE, "'process.priority' directive is ignored when FPM is not running as root"); } } // 设置master进程的pid fpm_globals.parent_pid = getpid(); for (wp = fpm_worker_all_pools; wp; wp = wp->next) { if (0 > fpm_unix_conf_wp(wp)) { return -1; } } return 0; }
int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */ { int is_root = !geteuid(); int made_chroot = 0; if (wp->config->rlimit_files) { struct rlimit r; r.rlim_max = r.rlim_cur = (rlim_t) wp->config->rlimit_files; if (0 > setrlimit(RLIMIT_NOFILE, &r)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_files for this pool. Please check your system limits or decrease rlimit_files. setrlimit(RLIMIT_NOFILE, %d)", wp->config->name, wp->config->rlimit_files); } } if (wp->config->rlimit_core) { struct rlimit r; r.rlim_max = r.rlim_cur = wp->config->rlimit_core == -1 ? (rlim_t) RLIM_INFINITY : (rlim_t) wp->config->rlimit_core; if (0 > setrlimit(RLIMIT_CORE, &r)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to set rlimit_core for this pool. Please check your system limits or decrease rlimit_core. setrlimit(RLIMIT_CORE, %d)", wp->config->name, wp->config->rlimit_core); } } if (is_root && wp->config->chroot && *wp->config->chroot) { if (0 > chroot(wp->config->chroot)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to chroot(%s)", wp->config->name, wp->config->chroot); return -1; } made_chroot = 1; } if (wp->config->chdir && *wp->config->chdir) { if (0 > chdir(wp->config->chdir)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to chdir(%s)", wp->config->name, wp->config->chdir); return -1; } } else if (made_chroot) { chdir("/"); } if (is_root) { if (wp->config->process_priority != 64) { if (setpriority(PRIO_PROCESS, 0, wp->config->process_priority) < 0) { zlog(ZLOG_SYSERROR, "[pool %s] Unable to set priority for this new process", wp->config->name); return -1; } } if (wp->set_gid) { if (0 > setgid(wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to setgid(%d)", wp->config->name, wp->set_gid); return -1; } } if (wp->set_uid) { if (0 > initgroups(wp->config->user, wp->set_gid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to initgroups(%s, %d)", wp->config->name, wp->config->user, wp->set_gid); return -1; } if (0 > setuid(wp->set_uid)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to setuid(%d)", wp->config->name, wp->set_uid); return -1; } } } #ifdef HAVE_PRCTL if (0 > prctl(PR_SET_DUMPABLE, 1, 0, 0, 0)) { zlog(ZLOG_SYSERROR, "[pool %s] failed to prctl(PR_SET_DUMPABLE)", wp->config->name); } #endif if (0 > fpm_clock_init()) { return -1; } return 0; }