/** * create timer */ int swTimer_init(int interval, int use_pipe) { swTimer *timer = &SwooleG.timer; timer->interval = interval; timer->lasttime = interval; #ifndef HAVE_TIMERFD SwooleG.use_timerfd = 0; #endif timer->list = swHashMap_new(SW_HASHMAP_INIT_BUCKET_N, free); if (!timer->list) { return SW_ERR; } if (SwooleG.use_timerfd) { if (swTimer_timerfd_set(timer, interval) < 0) { return SW_ERR; } timer->use_pipe = 0; } else { if (use_pipe) { if (swPipeNotify_auto(&timer->pipe, 0, 0) < 0) { return SW_ERR; } timer->fd = timer->pipe.getFd(&timer->pipe, 0); timer->use_pipe = 1; } else { timer->fd = 1; timer->use_pipe = 0; } if (swTimer_signal_set(timer, interval) < 0) { return SW_ERR; } swSignal_add(SIGALRM, swTimer_signal_handler); } if (timer->fd > 1) { SwooleG.main_reactor->setHandle(SwooleG.main_reactor, SW_FD_TIMER, swTimer_event_handler); SwooleG.main_reactor->add(SwooleG.main_reactor, SwooleG.timer.fd, SW_FD_TIMER); } timer->add = swTimer_add; timer->del = swTimer_del; timer->select = swTimer_select; timer->free = swTimer_free; return SW_OK; }
static PHP_METHOD(swoole_process, signal) { zval *callback = NULL; long signo = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &signo, &callback) == FAILURE) { return; } if (!SWOOLE_G(cli)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "cannot use swoole_process::signal here."); RETURN_FALSE; } if (SwooleGS->start) { if (signo == SIGTERM || signo == SIGALRM) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot use swoole_process::signal in swoole_server."); RETURN_FALSE; } } if (callback == NULL || ZVAL_IS_NULL(callback)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "no callback."); RETURN_FALSE; } char *func_name; if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { php_error_docref(NULL TSRMLS_CC, E_ERROR, "function '%s' is not callable", func_name); efree(func_name); RETURN_FALSE; } efree(func_name); sw_zval_add_ref(&callback); signal_callback[signo] = callback; #if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4 SwooleG.use_signalfd = 1; #else SwooleG.use_signalfd = 0; #endif php_swoole_check_reactor(); /** * for swSignalfd_setup */ SwooleG.main_reactor->check_signalfd = 1; swSignal_add(signo, php_swoole_onSignal); RETURN_TRUE; }
void swWorker_signal_init(void) { swSignal_add(SIGHUP, NULL); swSignal_add(SIGPIPE, NULL); swSignal_add(SIGUSR1, NULL); swSignal_add(SIGUSR2, NULL); swSignal_add(SIGTERM, swWorker_signal_handler); swSignal_add(SIGALRM, swTimer_signal_handler); //for test swSignal_add(SIGVTALRM, swWorker_signal_handler); }
static void swFactoryProcess_worker_signal_init(void) { swSignal_add(SIGHUP, NULL); swSignal_add(SIGPIPE, NULL); swSignal_add(SIGUSR1, NULL); swSignal_add(SIGUSR2, NULL); swSignal_add(SIGTERM, swFactoryProcess_worker_signal_handler); swSignal_add(SIGALRM, swTimer_signal_handler); //for test swSignal_add(SIGVTALRM, swFactoryProcess_worker_signal_handler); if (SwooleG.serv->daemonize) { swSignal_add(SIGINT, NULL); } }
void swWorker_signal_init(void) { swSignal_clear(); swSignal_add(SIGHUP, NULL); swSignal_add(SIGPIPE, NULL); swSignal_add(SIGUSR1, swWorker_signal_handler); swSignal_add(SIGUSR2, NULL); //swSignal_add(SIGINT, swWorker_signal_handler); swSignal_add(SIGTERM, swWorker_signal_handler); swSignal_add(SIGALRM, swSystemTimer_signal_handler); //for test swSignal_add(SIGVTALRM, swWorker_signal_handler); #ifdef SIGRTMIN swSignal_set(SIGRTMIN, swWorker_signal_handler, 1, 0); #endif }
static int swFactoryProcess_manager_loop(swFactory *factory) { int pid, new_pid; int i; int reload_worker_i = 0; int ret; int worker_exit_code; SwooleG.use_signalfd = 0; SwooleG.use_timerfd = 0; swFactoryProcess *object = factory->object; swServer *serv = factory->ptr; swWorker *reload_workers; if (serv->onManagerStart) { serv->onManagerStart(serv); } reload_workers = sw_calloc(serv->worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("[manager] malloc[reload_workers] failed"); return SW_ERR; } //for reload swSignal_add(SIGUSR1, swManagerSignalHanlde); while (SwooleG.running > 0) { pid = wait(&worker_exit_code); swTrace("[manager] worker stop.pid=%d\n", pid); if (pid < 0) { if (manager_worker_reloading == 0) { swTrace("[Manager] wait failed. Error: %s [%d]", strerror(errno), errno); } else if (manager_reload_flag == 0) { memcpy(reload_workers, object->workers, sizeof(swWorker) * serv->worker_num); manager_reload_flag = 1; goto kill_worker; } } if (SwooleG.running == 1) { for (i = 0; i < serv->worker_num; i++) { //对比pid if (pid != object->workers[i].pid) { continue; } else { if(serv->onWorkerError!=NULL && WEXITSTATUS(worker_exit_code) > 0) { serv->onWorkerError(serv, i, pid, WEXITSTATUS(worker_exit_code)); } pid = 0; new_pid = swFactoryProcess_worker_spawn(factory, i); if (new_pid < 0) { swWarn("Fork worker process failed. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } else { object->workers[i].pid = new_pid; } } } //task worker if(pid > 0) { swWorker *exit_worker = swHashMap_find_int(&SwooleG.task_workers.map, pid); if (exit_worker != NULL) { swProcessPool_spawn(exit_worker); } } } //reload worker kill_worker: if (manager_worker_reloading == 1) { //reload finish if (reload_worker_i >= serv->worker_num) { manager_worker_reloading = 0; reload_worker_i = 0; continue; } ret = kill(reload_workers[reload_worker_i].pid, SIGTERM); if (ret < 0) { swWarn("[Manager]kill failed, pid=%d. Error: %s [%d]", reload_workers[reload_worker_i].pid, strerror(errno), errno); continue; } reload_worker_i++; } } sw_free(reload_workers); if (serv->onManagerStop) { serv->onManagerStop(serv); } return SW_OK; }
static PHP_METHOD(swoole_process, signal) { zval *callback = NULL; long signo = 0; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lz", &signo, &callback) == FAILURE) { return; } if (!SWOOLE_G(cli)) { swoole_php_fatal_error(E_ERROR, "cannot use swoole_process::signal here."); RETURN_FALSE; } if (SwooleGS->start && (swIsWorker() || swIsMaster() || swIsManager() || swIsTaskWorker())) { if (signo == SIGTERM || signo == SIGALRM) { swoole_php_fatal_error(E_WARNING, "cannot use swoole_process::signal in swoole_server."); RETURN_FALSE; } } if (callback == NULL || ZVAL_IS_NULL(callback)) { callback = signal_callback[signo]; if (callback) { sw_zval_ptr_dtor(&callback); swSignal_add(signo, NULL); RETURN_TRUE; } else { swoole_php_error(E_WARNING, "no callback."); RETURN_FALSE; } } char *func_name; if (!sw_zend_is_callable(callback, 0, &func_name TSRMLS_CC)) { swoole_php_error(E_WARNING, "function '%s' is not callable", func_name); efree(func_name); RETURN_FALSE; } efree(func_name); #if PHP_MAJOR_VERSION >= 7 zval *tmp = emalloc(sizeof(zval)); memcpy(tmp, callback, sizeof(zval)); callback = tmp; #endif sw_zval_add_ref(&callback); if (signal_callback[signo]) { sw_zval_ptr_dtor(&callback); } signal_callback[signo] = callback; #if PHP_MAJOR_VERSION >= 7 || (PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4) SwooleG.use_signalfd = 1; #else SwooleG.use_signalfd = 0; #endif php_swoole_check_reactor(); /** * for swSignalfd_setup */ SwooleG.main_reactor->check_signalfd = 1; swSignal_add(signo, php_swoole_onSignal); RETURN_TRUE; }
static int swFactoryProcess_manager_loop(swFactory *factory) { int pid, new_pid; int i; int reload_worker_i = 0; int reload_worker_num; int ret; int worker_exit_code; SwooleG.use_signalfd = 0; SwooleG.use_timerfd = 0; memset(&ManagerProcess, 0, sizeof(ManagerProcess)); swServer *serv = factory->ptr; swWorker *reload_workers; if (serv->onManagerStart) { serv->onManagerStart(serv); } reload_worker_num = serv->worker_num + SwooleG.task_worker_num; reload_workers = sw_calloc(reload_worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("malloc[reload_workers] failed"); return SW_ERR; } //for reload swSignal_add(SIGTERM, swManager_signal_handle); swSignal_add(SIGUSR1, swManager_signal_handle); swSignal_add(SIGUSR2, swManager_signal_handle); //swSignal_add(SIGINT, swManager_signal_handle); while (SwooleG.running > 0) { pid = wait(&worker_exit_code); if (pid < 0) { if (ManagerProcess.reloading == 0) { swTrace("wait() failed. Error: %s [%d]", strerror(errno), errno); } else if (ManagerProcess.reload_event_worker == 1) { memcpy(reload_workers, serv->workers, sizeof(swWorker) * serv->worker_num); reload_worker_num = serv->worker_num; if (SwooleG.task_worker_num > 0) { memcpy(reload_workers + serv->worker_num, SwooleG.task_workers.workers, sizeof(swWorker) * SwooleG.task_worker_num); reload_worker_num += SwooleG.task_worker_num; } reload_worker_i = 0; ManagerProcess.reload_event_worker = 0; goto kill_worker; } else if (ManagerProcess.reload_task_worker == 1) { if (SwooleG.task_worker_num == 0) { swWarn("Cannot reload workers, because server no have task workers."); continue; } memcpy(reload_workers, SwooleG.task_workers.workers, sizeof(swWorker) * SwooleG.task_worker_num); reload_worker_num = SwooleG.task_worker_num; reload_worker_i = 0; ManagerProcess.reload_task_worker = 0; goto kill_worker; } } if (SwooleG.running == 1) { for (i = 0; i < serv->worker_num; i++) { //compare PID if (pid != serv->workers[i].pid) { continue; } else { if (serv->onWorkerError != NULL && WEXITSTATUS(worker_exit_code) > 0) { serv->onWorkerError(serv, i, pid, WEXITSTATUS(worker_exit_code)); } pid = 0; while (1) { new_pid = swFactoryProcess_worker_spawn(factory, i); if (new_pid < 0) { usleep(100000); continue; } else { serv->workers[i].pid = new_pid; break; } } } } //task worker if (pid > 0) { swWorker *exit_worker = swHashMap_find_int(SwooleG.task_workers.map, pid); if (exit_worker != NULL) { swProcessPool_spawn(exit_worker); } } } //reload worker kill_worker: if (ManagerProcess.reloading == 1) { //reload finish if (reload_worker_i >= reload_worker_num) { ManagerProcess.reloading = 0; reload_worker_i = 0; continue; } ret = kill(reload_workers[reload_worker_i].pid, SIGTERM); if (ret < 0) { swSysError("[Manager]kill(%d) failed.", reload_workers[reload_worker_i].pid); continue; } reload_worker_i++; } } sw_free(reload_workers); //kill all child process for (i = 0; i < serv->worker_num; i++) { swTrace("[Manager]kill worker processor"); kill(serv->workers[i].pid, SIGTERM); } if (SwooleG.task_worker_num > 0) { swProcessPool_shutdown(&SwooleG.task_workers); } if (serv->onManagerStop) { serv->onManagerStop(serv); } return SW_OK; }