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 int swProcessPool_main_loop(swProcessPool *ma) { int pid, new_pid; int i, writer_pti; int reload_worker_i = 0; int ret; swWorker *reload_workers; reload_workers = sw_calloc(ma->worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("[manager] malloc[reload_workers] fail.\n"); return SW_ERR; } while (1) { pid = wait(NULL);exit(0); swTrace("[manager] worker stop.pid=%d\n", pid); if (pid < 0) { if (ma->reloading == 0) { swTrace("[Manager] wait fail. Error: %s [%d]", strerror(errno), errno); } else if (ma->reload_flag == 0) { memcpy(reload_workers, ma->workers, sizeof(swWorker) * ma->worker_num); ma->reload_flag = 1; goto reload_worker; } } if (swoole_running == 1) { swWorker *exit_worker = swHashMap_find_int(&ma->map, pid); if (exit_worker == NULL) { swWarn("[Manager]unknow worker[pid=%d]", pid); } new_pid = swProcessPool_spawn(ma, exit_worker); if (new_pid < 0) { swWarn("Fork worker process fail. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } swHashMap_del_int(&ma->map, pid); } //reload worker reload_worker: if (ma->reloading == 1) { //reload finish if (reload_worker_i >= ma->worker_num) { ma->reloading = 0; reload_worker_i = 0; continue; } ret = kill(reload_workers[reload_worker_i].pid, SIGTERM); if (ret < 0) { swWarn("[Manager]kill fail.pid=%d. Error: %s [%d]", reload_workers[reload_worker_i].pid, strerror(errno), errno); continue; } reload_worker_i++; } } return SW_OK; }
int swProcessPool_wait(swProcessPool *pool) { int pid, new_pid; int reload_worker_i = 0; int ret; swWorker *reload_workers; reload_workers = sw_calloc(pool->worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("[manager] malloc[reload_workers] fail.\n"); return SW_ERR; } while (1) { pid = wait(NULL); if (pid < 0) { if (pool->reloading == 0) { swTrace("[Manager] wait failed. Error: %s [%d]", strerror(errno), errno); } else if (pool->reload_flag == 0) { swTrace("[Manager] reload workers."); memcpy(reload_workers, pool->workers, sizeof(swWorker) * pool->worker_num); pool->reload_flag = 1; goto reload_worker; } } swTrace("[Manager] worker stop.pid=%d", pid); if (SwooleG.running == 1) { swWorker *exit_worker = swHashMap_find_int(pool->map, pid); if (exit_worker == NULL) { swWarn("[Manager]unknow worker[pid=%d]", pid); continue; } new_pid = swProcessPool_spawn(exit_worker); if (new_pid < 0) { swWarn("Fork worker process failed. Error: %s [%d]", strerror(errno), errno); return SW_ERR; } swHashMap_del_int(pool->map, pid); } //reload worker reload_worker: if (pool->reloading == 1) { //reload finish if (reload_worker_i >= pool->worker_num) { pool->reloading = 0; reload_worker_i = 0; continue; } ret = kill(reload_workers[reload_worker_i].pid, SIGTERM); if (ret < 0) { swWarn("[Manager]kill fail.pid=%d. Error: %s [%d]", reload_workers[reload_worker_i].pid, strerror(errno), errno); continue; } reload_worker_i++; } } return SW_OK; }
static int http_onReceive(swFactory *factory, swEventData *req) { TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); int fd = req->info.fd; http_client *client = swHashMap_find_int(php_sw_http_clients, fd); if (!client) { client = http_client_new(fd TSRMLS_CC); } php_http_parser *parser = &client->parser; zval *zrequest; MAKE_STD_ZVAL(zrequest); object_init_ex(zrequest, swoole_http_request_class_entry_ptr); zval *header; MAKE_STD_ZVAL(header); //request header array_init(header); zend_update_property(swoole_http_request_class_entry_ptr, zrequest, ZEND_STRL("header"), header TSRMLS_CC); zval *zresponse; MAKE_STD_ZVAL(zresponse); object_init_ex(zresponse, swoole_http_response_class_entry_ptr); //socket fd zend_update_property_long(swoole_http_response_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC); client->zresponse = zresponse; client->zrequest = zrequest; parser->data = client; php_http_parser_init(parser, PHP_HTTP_REQUEST); zval *zdata = php_swoole_get_data(req TSRMLS_CC); size_t n = php_http_parser_execute(parser, &http_parser_settings, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); zval_ptr_dtor(&zdata); if (n < 0) { swWarn("php_http_parser_execute failed."); } else { zval *retval; zval **args[2]; args[0] = &zrequest; args[1] = &zresponse; if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[0], &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "onRequest handler error"); } if (EG(exception)) { zend_exception_error(EG(exception), E_WARNING TSRMLS_CC); } if (retval) { zval_ptr_dtor(&retval); } } return SW_OK; }
int swProcessPool_wait(swProcessPool *pool) { int pid, new_pid; int reload_worker_i = 0; int ret; int status; swWorker *reload_workers; reload_workers = sw_calloc(pool->worker_num, sizeof(swWorker)); if (reload_workers == NULL) { swError("[manager] malloc[reload_workers] fail.\n"); return SW_ERR; } while (SwooleG.running) { pid = wait(&status); if (pid < 0) { if (pool->reloading == 0) { swTrace("[Manager] wait failed. Error: %s [%d]", strerror(errno), errno); } else if (pool->reload_flag == 0) { swTrace("[Manager] reload workers."); memcpy(reload_workers, pool->workers, sizeof(swWorker) * pool->worker_num); pool->reload_flag = 1; goto reload_worker; } else if (SwooleG.running == 0) { break; } } swTrace("[Manager] worker stop.pid=%d", pid); if (SwooleG.running == 1) { swWorker *exit_worker = swHashMap_find_int(pool->map, pid); if (exit_worker == NULL) { if (pool->onWorkerNotFound) { pool->onWorkerNotFound(pool, pid); } else { swWarn("[Manager]unknow worker[pid=%d]", pid); } continue; } if (!WIFEXITED(status)) { swWarn("worker#%d abnormal exit, status=%d, signal=%d", exit_worker->id, WEXITSTATUS(status), WTERMSIG(status)); } new_pid = swProcessPool_spawn(exit_worker); if (new_pid < 0) { swWarn("Fork worker process failed. Error: %s [%d]", strerror(errno), errno); sw_free(reload_workers); return SW_ERR; } swHashMap_del_int(pool->map, pid); } //reload worker reload_worker: if (pool->reloading == 1) { //reload finish if (reload_worker_i >= pool->worker_num) { pool->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); return SW_OK; }
static int http_onReceive(swFactory *factory, swEventData *req) { TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); int fd = req->info.fd; // swTrace("on receive:%s pid:%d\n", zdata, getpid()); swConnection *conn = swServer_connection_get(SwooleG.serv, fd); if(conn->websocket_status == WEBSOCKET_STATUS_HANDSHAKE) //websocket callback { zval *zdata = php_swoole_get_data(req TSRMLS_CC); swTrace("on message callback\n"); char *buf = Z_STRVAL_P(zdata); long fin = buf[0] ? 1 : 0; long opcode = buf[1] ? 1 : 0; buf+=2; zval *zresponse; MAKE_STD_ZVAL(zresponse); object_init_ex(zresponse, swoole_http_wsresponse_class_entry_ptr); //socket fd zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fd"), fd TSRMLS_CC); zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("fin"), fin TSRMLS_CC); zend_update_property_long(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("opcode"), opcode TSRMLS_CC); zend_update_property_stringl(swoole_http_wsresponse_class_entry_ptr, zresponse, ZEND_STRL("data"), buf, (Z_STRLEN_P(zdata)-2) TSRMLS_CC); zval **args[1]; args[0] = &zresponse; zval *retval; if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[1], &retval, 1, args, 0, NULL TSRMLS_CC) == FAILURE) { zval_ptr_dtor(&zdata); php_error_docref(NULL TSRMLS_CC, E_WARNING, "onMessage handler error"); } swTrace("===== message callback end======"); if (EG(exception)) { zval_ptr_dtor(&zdata); zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { zval_ptr_dtor(&retval); } zval_ptr_dtor(&zdata); return SW_OK; } http_client *client = swHashMap_find_int(php_sw_http_clients, fd); if (!client) { client = http_client_new(fd TSRMLS_CC); } php_http_parser *parser = &client->parser; /** * create request and response object */ http_request_new(client TSRMLS_CC); parser->data = client; php_http_parser_init(parser, PHP_HTTP_REQUEST); zval *zdata = php_swoole_get_data(req TSRMLS_CC); //server info zval *_request; MAKE_STD_ZVAL(_request); array_init(_request); zend_update_property(swoole_http_request_class_entry_ptr, client->zrequest, ZEND_STRL("request"), _request TSRMLS_CC); size_t n = php_http_parser_execute(parser, &http_parser_settings, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata)); zval_ptr_dtor(&zdata); if (n < 0) { swWarn("php_http_parser_execute failed."); if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) { SwooleG.serv->factory.end(&SwooleG.serv->factory, fd); } } else { if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) // need handshake { if(php_sw_http_server_callbacks[2] == NULL) { int ret = websocket_handshake(client); http_request_free(client TSRMLS_CC); if (ret == SW_ERR) { swTrace("websocket handshake error\n"); SwooleG.serv->factory.end(&SwooleG.serv->factory, fd); } else { handshake_success(fd); swTrace("websocket handshake_success\n"); return SW_OK; } return ret; } } zval *retval; zval **args[2]; zval *zrequest = client->zrequest; //server info zval *zserver; MAKE_STD_ZVAL(zserver); array_init(zserver); zend_update_property(swoole_http_request_class_entry_ptr, zrequest, ZEND_STRL("server"), zserver TSRMLS_CC); switch (parser->method) { case PHP_HTTP_GET: add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);break; case PHP_HTTP_POST: add_assoc_string(zserver, "REQUEST_METHOD", "POST", 1);break; case PHP_HTTP_HEAD: add_assoc_string(zserver, "REQUEST_METHOD", "HEAD", 1);break; case PHP_HTTP_PUT: add_assoc_string(zserver, "REQUEST_METHOD", "PUT", 1);break; case PHP_HTTP_DELETE: add_assoc_string(zserver, "REQUEST_METHOD", "DELETE", 1);break; case PHP_HTTP_PATCH: add_assoc_string(zserver, "REQUEST_METHOD", "PATCH", 1);break; /* pathological */ case PHP_HTTP_CONNECT: add_assoc_string(zserver, "REQUEST_METHOD", "CONNECT", 1);break; case PHP_HTTP_OPTIONS: add_assoc_string(zserver, "REQUEST_METHOD", "OPTIONS", 1);break; case PHP_HTTP_TRACE: add_assoc_string(zserver, "REQUEST_METHOD", "TRACE", 1);break; /* webdav */ case PHP_HTTP_COPY: add_assoc_string(zserver, "REQUEST_METHOD", "COPY", 1);break; case PHP_HTTP_LOCK: add_assoc_string(zserver, "REQUEST_METHOD", "LOCK", 1);break; case PHP_HTTP_MKCOL: add_assoc_string(zserver, "REQUEST_METHOD", "MKCOL", 1);break; case PHP_HTTP_MOVE: add_assoc_string(zserver, "REQUEST_METHOD", "MOVE", 1);break; case PHP_HTTP_PROPFIND: add_assoc_string(zserver, "REQUEST_METHOD", "PROPFIND", 1);break; case PHP_HTTP_PROPPATCH: add_assoc_string(zserver, "REQUEST_METHOD", "PROPPATCH", 1);break; case PHP_HTTP_UNLOCK: add_assoc_string(zserver, "REQUEST_METHOD", "UNLOCK", 1);break; /* subversion */ case PHP_HTTP_REPORT: add_assoc_string(zserver, "REQUEST_METHOD", "REPORT", 1);break; case PHP_HTTP_MKACTIVITY: add_assoc_string(zserver, "REQUEST_METHOD", "MKACTIVITY", 1);break; case PHP_HTTP_CHECKOUT: add_assoc_string(zserver, "REQUEST_METHOD", "CHECKOUT", 1);break; case PHP_HTTP_MERGE: add_assoc_string(zserver, "REQUEST_METHOD", "MERGE", 1);break; /* upnp */ case PHP_HTTP_MSEARCH: add_assoc_string(zserver, "REQUEST_METHOD", "MSEARCH", 1);break; case PHP_HTTP_NOTIFY: add_assoc_string(zserver, "REQUEST_METHOD", "NOTIFY", 1);break; case PHP_HTTP_SUBSCRIBE: add_assoc_string(zserver, "REQUEST_METHOD", "SUBSCRIBE", 1);break; case PHP_HTTP_UNSUBSCRIBE: add_assoc_string(zserver, "REQUEST_METHOD", "UNSUBSCRIBE", 1);break; case PHP_HTTP_NOT_IMPLEMENTED: add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1);break; } // if (parser->method == PHP_HTTP_POST) // { // add_assoc_string(zserver, "REQUEST_METHOD", "POST", 1); // } // else // { // add_assoc_string(zserver, "REQUEST_METHOD", "GET", 1); // } add_assoc_stringl(zserver, "REQUEST_URI", client->request.path, client->request.path_len, 1); add_assoc_stringl(zserver, "PATH_INFO", client->request.path, client->request.path_len, 1); add_assoc_long_ex(zserver, ZEND_STRS("REQUEST_TIME"), SwooleGS->now); swConnection *conn = swServer_connection_get(SwooleG.serv, fd); add_assoc_long(zserver, "SERVER_PORT", SwooleG.serv->connection_list[conn->from_fd].addr.sin_port); add_assoc_long(zserver, "REMOTE_PORT", ntohs(conn->addr.sin_port)); add_assoc_string(zserver, "REMOTE_ADDR", inet_ntoa(conn->addr.sin_addr), 1); if (client->request.version == 101) { add_assoc_string(zserver, "SERVER_PROTOCOL", "HTTP/1.1", 1); } else { add_assoc_string(zserver, "SERVER_PROTOCOL", "HTTP/1.0", 1); } add_assoc_string(zserver, "SERVER_SOFTWARE", SW_HTTP_SERVER_SOFTWARE, 1); add_assoc_string(zserver, "GATEWAY_INTERFACE", SW_HTTP_SERVER_SOFTWARE, 1); // ZEND_SET_SYMBOL(&EG(symbol_table), "_SERVER", zserver); zval *zresponse; MAKE_STD_ZVAL(zresponse); object_init_ex(zresponse, swoole_http_response_class_entry_ptr); //socket fd zend_update_property_long(swoole_http_response_class_entry_ptr, zresponse, ZEND_STRL("fd"), client->fd TSRMLS_CC); client->zresponse = zresponse; args[0] = &zrequest; args[1] = &zresponse; int called = 0; if(conn->websocket_status == WEBSOCKET_STATUS_CONNECTION) { called = 2; } if (call_user_function_ex(EG(function_table), NULL, php_sw_http_server_callbacks[called], &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "onRequest handler error"); } if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } if (retval) { zval_ptr_dtor(&retval); } swTrace("======call end======\n"); if(called == 2) { handshake_success(fd); } } return SW_OK; }
static void php_swoole_aio_onComplete(swAio_event *event) { int isEOF = SW_FALSE; int64_t ret; zval *retval = NULL, *zcallback = NULL, *zwriten = NULL; zval *zcontent = NULL; zval **args[2]; file_request *file_req = NULL; dns_request *dns_req = NULL; #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #else zval _zcontent; zval _zwriten; bzero(&_zcontent, sizeof(zval)); bzero(&_zwriten, sizeof(zval)); #endif if (event->type == SW_AIO_GETHOSTBYNAME) { dns_req = (dns_request *) event->req; if (dns_req->callback == NULL) { swoole_php_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[0]"); return; } zcallback = dns_req->callback; } else { file_req = swHashMap_find_int(php_swoole_aio_request, event->task_id); if (!file_req) { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[1]"); return; } if (file_req->callback == NULL && file_req->type == SW_AIO_READ) { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete callback not found[2]"); return; } zcallback = file_req->callback; } ret = event->ret; if (ret < 0) { SwooleG.error = event->error; swoole_php_error(E_WARNING, "Aio Error: %s[%d]", strerror(event->error), event->error); } else if (file_req != NULL) { if (ret == 0) { bzero(event->buf, event->nbytes); isEOF = SW_TRUE; } else if (file_req->once == 1 && ret < file_req->length) { swoole_php_fatal_error(E_WARNING, "ret_length[%d] < req->length[%d].", (int ) ret, file_req->length); } else if (event->type == SW_AIO_READ) { file_req->offset += event->ret; } } if (event->type == SW_AIO_READ) { args[0] = &file_req->filename; args[1] = &zcontent; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif if (ret < 0) { SW_ZVAL_STRING(zcontent, "", 1); } else { SW_ZVAL_STRINGL(zcontent, event->buf, ret, 1); } } else if (event->type == SW_AIO_WRITE) { #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zwriten); #else zwriten = &_zwriten; #endif args[0] = &file_req->filename; args[1] = &zwriten; ZVAL_LONG(zwriten, ret); } else if(event->type == SW_AIO_GETHOSTBYNAME) { args[0] = &dns_req->domain; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif if (ret < 0) { SW_ZVAL_STRING(zcontent, "", 1); } else { SW_ZVAL_STRING(zcontent, event->buf, 1); } args[1] = &zcontent; } else { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete unknown event type[%d].", event->type); return; } if (zcallback) { if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { swoole_php_fatal_error(E_WARNING, "swoole_async: onAsyncComplete handler error"); return; } if (EG(exception)) { zend_exception_error(EG(exception), E_ERROR TSRMLS_CC); } } //file io if (file_req) { if (file_req->once == 1) { close_file: close(event->fd); swHashMap_del_int(php_swoole_aio_request, event->task_id); } else if(file_req->type == SW_AIO_WRITE) { if (retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval)) { swHashMap_del(php_swoole_open_files, Z_STRVAL_P(file_req->filename), Z_STRLEN_P(file_req->filename)); goto close_file; } else { swHashMap_del_int(php_swoole_aio_request, event->task_id); } } else { if ((retval != NULL && !ZVAL_IS_NULL(retval) && !Z_BVAL_P(retval)) || isEOF) { goto close_file; } //Less than expected, at the end of the file else if (event->ret < event->nbytes) { event->ret = 0; php_swoole_aio_onComplete(event); } //continue to read else { int ret = SwooleAIO.read(event->fd, event->buf, event->nbytes, file_req->offset); if (ret < 0) { swoole_php_fatal_error(E_WARNING, "swoole_async: continue to read failed. Error: %s[%d]", strerror(event->error), event->error); goto close_file; } else { swHashMap_move_int(php_swoole_aio_request, event->task_id, ret); } } } } else if (dns_req) { sw_zval_ptr_dtor(&dns_req->callback); sw_zval_ptr_dtor(&dns_req->domain); efree(dns_req); efree(event->buf); } if (zcontent) { sw_zval_ptr_dtor(&zcontent); } if (zwriten) { sw_zval_ptr_dtor(&zwriten); } if (retval) { sw_zval_ptr_dtor(&retval); } }
static void php_swoole_aio_onComplete(swAio_event *event) { int isEOF = SW_FALSE; int64_t ret; zval *retval = NULL, *zcallback = NULL, *zwriten = NULL; zval *zcontent = NULL; zval **args[2]; file_request *file_req = NULL; dns_request *dns_req = NULL; #if PHP_MAJOR_VERSION < 7 TSRMLS_FETCH_FROM_CTX(sw_thread_ctx ? sw_thread_ctx : NULL); #else zval _zcontent; zval _zwriten; #endif if (event->type == SW_AIO_DNS_LOOKUP) { dns_req = (dns_request *) event->req; if (dns_req->callback == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete callback not found[0]"); return; } zcallback = dns_req->callback; } else { file_req = swHashMap_find_int(php_swoole_aio_request, event->fd); if (!file_req) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete callback not found[1]"); return; } if (file_req->callback == NULL && file_req->type == SW_AIO_READ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete callback not found[2]"); return; } zcallback = file_req->callback; } ret = event->ret; if (ret < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: Aio Error: %s[%d]", strerror(event->error), event->error); } else if (file_req != NULL) { if (ret == 0) { bzero(event->buf, event->nbytes); isEOF = SW_TRUE; } else if (file_req->once == 1 && ret < file_req->content_length) { swoole_php_fatal_error(E_WARNING, "swoole_async: ret_length[%d] < req->length[%d].", (int) ret, file_req->content_length); } else if (event->type == SW_AIO_READ) { file_req->offset += event->ret; } } if (event->type == SW_AIO_READ) { args[0] = &file_req->filename; args[1] = &zcontent; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif memset(event->buf + ret, 0, 1); SW_ZVAL_STRINGL(zcontent, event->buf, ret, 1); } else if (event->type == SW_AIO_WRITE) { #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zwriten); #else zwriten = &_zwriten; #endif args[0] = &file_req->filename; args[1] = &zwriten; ZVAL_LONG(zwriten, ret); if (file_req->once != 1) { swoole_aio_free(event->buf); } } else if(event->type == SW_AIO_DNS_LOOKUP) { args[0] = &dns_req->domain; #if PHP_MAJOR_VERSION < 7 SW_MAKE_STD_ZVAL(zcontent); #else zcontent = &_zcontent; #endif if (ret < 0) { SW_ZVAL_STRING(zcontent, "", 1); } else { SW_ZVAL_STRING(zcontent, event->buf, 1); } args[1] = &zcontent; } else { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete unknow event type"); return; } if (zcallback) { if (sw_call_user_function_ex(EG(function_table), NULL, zcallback, &retval, 2, args, 0, NULL TSRMLS_CC) == FAILURE) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: onAsyncComplete handler error"); return; } } //readfile/writefile if (file_req != NULL) { if (file_req->once == 1) { close_file: sw_zval_ptr_dtor(&file_req->callback); sw_zval_ptr_dtor(&file_req->filename); swoole_aio_free(event->buf); close(event->fd); swHashMap_del_int(php_swoole_aio_request, event->fd); efree(file_req); } else if(file_req->type == SW_AIO_WRITE) { if (retval != NULL && !Z_BVAL_P(retval)) { swHashMap_del(php_swoole_open_files, Z_STRVAL_P(file_req->filename), Z_STRLEN_P(file_req->filename)); goto close_file; } } else { if (!Z_BVAL_P(retval) || isEOF) { goto close_file; } else if (SwooleAIO.read(event->fd, event->buf, event->nbytes, file_req->offset) < 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "swoole_async: continue to read failed. Error: %s[%d]", strerror(event->error), event->error); } } } else if (dns_req != NULL) { sw_zval_ptr_dtor(&dns_req->callback); sw_zval_ptr_dtor(&dns_req->domain); efree(dns_req); efree(event->buf); } if (zcontent != NULL) { sw_zval_ptr_dtor(&zcontent); } if (zwriten != NULL) { sw_zval_ptr_dtor(&zwriten); } if (retval != NULL) { sw_zval_ptr_dtor(&retval); } }
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; }