diff --git a/.github/workflows/alpine.Dockerfile b/.github/workflows/alpine.Dockerfile index fb76e422204..494bb252deb 100644 --- a/.github/workflows/alpine.Dockerfile +++ b/.github/workflows/alpine.Dockerfile @@ -1,23 +1,23 @@ ARG PHP_VERSION ARG ALPINE_VERSION -FROM hyperf/hyperf:${PHP_VERSION}-alpine-v${ALPINE_VERSION}-dev +FROM phpswoole/php:${PHP_VERSION}-alpine LABEL maintainer="Swoole Team " version="1.0" license="Apache2" ARG PHP_VERSION -COPY . /opt/www +COPY . /swoole -WORKDIR /opt/www +WORKDIR /swoole RUN set -ex \ && phpize \ && ./configure --enable-openssl --enable-swoole-curl \ - && make -s -j$(nproc) && make install \ - && echo "extension=swoole.so" > /etc/php$(echo $PHP_VERSION | sed 's/\.//g')/conf.d/50_swoole.ini \ - # check - && php -v \ - && php -m \ - && php --ri swoole \ - && echo -e "\033[42;37m Build Completed :).\033[0m\n" + && make -s -j$(nproc) && make install + +RUN echo "extension=swoole.so" > "/usr/local/etc/php/conf.d/swoole.ini" +RUN php -v +RUN php -m +RUN php --ri swoole +RUN echo -e "\033[42;37m Build Completed :).\033[0m\n" diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 2bd04f285e0..1c9d4a6cec9 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -9,6 +9,7 @@ jobs: build: runs-on: ubuntu-latest if: "!contains(github.event.head_commit.message, '--filter=') || contains(github.event.head_commit.message, '[core]')" + timeout-minutes: 15 services: tinyproxy: image: "vimagick/tinyproxy" diff --git a/.github/workflows/ext.yml b/.github/workflows/ext.yml index 6806851b32d..7b25873a805 100644 --- a/.github/workflows/ext.yml +++ b/.github/workflows/ext.yml @@ -41,11 +41,11 @@ jobs: make clean && make -j$(nproc) build-macos-latest: - if: "!contains(github.event.head_commit.message, '--filter=')" + if: "!contains(github.event.head_commit.message, '--filter=') || contains(github.event.head_commit.message, '[macos]')" runs-on: macos-latest steps: - name: install dependencies - run: brew reinstall php + run: brew reinstall php@8.3 && brew link php@8.3 --force - uses: actions/checkout@v4 - name: phpize run: phpize @@ -70,23 +70,11 @@ jobs: make clean && make -j$(sysctl -n hw.ncpu) build-alpine-latest: - if: "!contains(github.event.head_commit.message, '--filter=')" + if: "!contains(github.event.head_commit.message, '--filter=') || contains(github.event.head_commit.message, '[alpine]')" runs-on: ubuntu-latest strategy: matrix: - php-version: [ '8.1', '8.2', '8.3' ] - alpine-version: [ '3.16', '3.17', '3.18', '3.19', 'edge' ] - exclude: - - php-version: '8.3' - alpine-version: '3.16' - - php-version: '8.3' - alpine-version: '3.17' - - php-version: '8.3' - alpine-version: '3.18' - - php-version: '8.2' - alpine-version: '3.16' - - php-version: '8.2' - alpine-version: '3.17' + php-version: [ '8.0', '8.1', '8.2', '8.3' ] max-parallel: 8 fail-fast: false steps: @@ -94,4 +82,4 @@ jobs: - name: build run: | cp .github/workflows/alpine.Dockerfile alpine.Dockerfile - docker build -t swoole . -f alpine.Dockerfile --build-arg PHP_VERSION=${{ matrix.php-version }} --build-arg ALPINE_VERSION=${{ matrix.alpine-version }} + docker build -t swoole . -f alpine.Dockerfile --build-arg PHP_VERSION=${{ matrix.php-version }} diff --git a/.github/workflows/unit.yml b/.github/workflows/unit.yml index eccdbae5bbb..299e205a02b 100644 --- a/.github/workflows/unit.yml +++ b/.github/workflows/unit.yml @@ -6,6 +6,7 @@ jobs: test-linux: runs-on: ubuntu-latest if: "!contains(github.event.head_commit.message, '--filter=') || contains(github.event.head_commit.message, '[unit]')" + timeout-minutes: 15 strategy: fail-fast: false matrix: diff --git a/CMakeLists.txt b/CMakeLists.txt index 34c01d81667..31dc1ab6faf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,12 +1,12 @@ PROJECT(libswoole) +cmake_minimum_required(VERSION 2.8.12) ENABLE_LANGUAGE(ASM) -set(SWOOLE_VERSION 5.1.4) +set(SWOOLE_VERSION 5.1.6) set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") -cmake_minimum_required(VERSION 2.8) file(READ ./config.h SWOOLE_CONFIG_FILE) @@ -122,7 +122,8 @@ link_directories(${LIBRARY_OUTPUT_PATH}) add_library(lib-swoole SHARED ${SRC_LIST}) set_target_properties(lib-swoole PROPERTIES OUTPUT_NAME "swoole" VERSION ${SWOOLE_VERSION}) target_link_libraries(lib-swoole ${SWOOLE_LINK_LIBRARIES}) -if(CODE_COVERAGE) + +if (CODE_COVERAGE) target_link_libraries(lib-swoole coverage_config gcov) endif(CODE_COVERAGE) diff --git a/composer.json b/composer.json new file mode 100644 index 00000000000..e80595b93ea --- /dev/null +++ b/composer.json @@ -0,0 +1,66 @@ +{ + "name": "swoole/swoole", + "type": "php-ext", + "license": "Apache-2.0", + "description": "Swoole is an event-driven, asynchronous, coroutine-based concurrency library with high performance for PHP.", + "require": { + "php": ">= 8.0" + }, + "php-ext": { + "extension-name": "swoole", + "configure-options": [ + { + "name": "enable-sockets", + "description": "Enable sockets support" + }, + { + "name": "enable-openssl", + "description": "Enable openssl support" + }, + { + "name": "with-openssl-dir", + "description": "Include OpenSSL support (requires OpenSSL >= 1.0.2)", + "needs-value": true + }, + { + "name": "enable-mysqlnd", + "description": "Enable mysqlnd support" + }, + { + "name": "enable-swoole-curl", + "description": "Enable curl support" + }, + { + "name": "enable-cares", + "description": "Enable cares support" + }, + { + "name": "enable-brotli", + "description": "Enable brotli support" + }, + { + "name": "with-brotli-dir", + "description": "Include Brotli support", + "needs-value": true + }, + { + "name": "enable-swoole-pgsql", + "description": "Enable PostgreSQL database support" + }, + { + "name": "with-swoole-odbc", + "description": "Enable ODBC database support", + "needs-value": true + }, + { + "name": "with-swoole-oracle", + "description": "Enable Oracle database support", + "needs-value": true + }, + { + "name": "enable-swoole-sqlite", + "description": "Enable Sqlite database support" + } + ] + } +} \ No newline at end of file diff --git a/core-tests/CMakeLists.txt b/core-tests/CMakeLists.txt index a9d66ebf37c..8f28da5bb47 100755 --- a/core-tests/CMakeLists.txt +++ b/core-tests/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 2.8.1) +cmake_minimum_required(VERSION 2.8.12) project(core_tests) @@ -10,14 +10,14 @@ file(GLOB_RECURSE SOURCE_FILES FOLLOW_SYMLINKS src/*.cpp deps/llhttp/src/*.c) add_definitions(-DHAVE_CONFIG_H) -set(core_tests_includes ./include/ ../thirdparty ../thirdparty/hiredis ./deps/llhttp/include) +set(core_tests_includes ./include/ ../thirdparty ../thirdparty/hiredis ./deps/llhttp/include /usr/local/include) set(core_tests_libraries) set(core_tests_link_directories /usr/local/lib) -list(APPEND core_tests_libraries pthread) +list(APPEND core_tests_libraries pthread gtest gtest_main) # find GTest -find_package(GTest) +find_package(GTest REQUIRED) if (!${GTEST_FOUND}) message(FATAL_ERROR "Not found GTest") endif() diff --git a/core-tests/src/network/dns.cpp b/core-tests/src/network/dns.cpp index cc7cd230024..76c6a4efc2f 100644 --- a/core-tests/src/network/dns.cpp +++ b/core-tests/src/network/dns.cpp @@ -74,23 +74,9 @@ TEST(dns, cancel) { } TEST(dns, getaddrinfo) { - char buf[1024] = {}; - swoole::network::GetaddrinfoRequest req = {}; - req.hostname = "www.baidu.com"; - req.family = AF_INET; - req.socktype = SOCK_STREAM; - req.protocol = 0; - req.service = nullptr; - req.result = buf; + swoole::GetaddrinfoRequest req("www.baidu.com", AF_INET, SOCK_STREAM, 0, ""); ASSERT_EQ(swoole::network::getaddrinfo(&req), 0); ASSERT_GT(req.count, 0); - - vector ip_list; - req.parse_result(ip_list); - - for (auto &ip : ip_list) { - ASSERT_TRUE(swoole::network::Address::verify_ip(AF_INET, ip)); - } } TEST(dns, load_resolv_conf) { diff --git a/core-tests/src/server/server.cpp b/core-tests/src/server/server.cpp index c66e88a64aa..3239e316cee 100644 --- a/core-tests/src/server/server.cpp +++ b/core-tests/src/server/server.cpp @@ -499,7 +499,7 @@ TEST(server, task_worker) { exit(2); } - serv.onTask = [](Server *serv, swEventData *task) -> int { + serv.onTask = [](Server *serv, EventData *task) -> int { EXPECT_EQ(serv->get_task_count(), 1); EXPECT_EQ(string(task->data, task->info.len), string(packet)); serv->gs->task_workers.running = 0; @@ -512,7 +512,9 @@ TEST(server, task_worker) { thread t1([&serv]() { serv.gs->task_workers.running = 1; serv.gs->tasking_num++; - serv.gs->task_workers.main_loop(&serv.gs->task_workers, &serv.gs->task_workers.workers[0]); + Worker *worker = &serv.gs->task_workers.workers[0]; + worker->init(); + serv.gs->task_workers.main_loop(&serv.gs->task_workers, worker); serv.gs->tasking_num--; EXPECT_EQ(serv.get_task_count(), 0); serv.gs->tasking_num--; diff --git a/ext-src/php_swoole.cc b/ext-src/php_swoole.cc index dc6cb10159d..a8b249e2b7e 100644 --- a/ext-src/php_swoole.cc +++ b/ext-src/php_swoole.cc @@ -17,13 +17,13 @@ #include "php_swoole_library.h" #include "php_swoole_process.h" -#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) -#include "ext/pcre/php_pcre.h" -#endif +BEGIN_EXTERN_C() #include "zend_exceptions.h" #include "zend_extensions.h" -BEGIN_EXTERN_C() +#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE) +#include "ext/pcre/php_pcre.h" +#endif #include "ext/json/php_json.h" #include "stubs/php_swoole_arginfo.h" @@ -340,7 +340,18 @@ SW_API bool php_swoole_is_enable_coroutine() { SW_API zend_long php_swoole_parse_to_size(zval *zv) { if (ZVAL_IS_STRING(zv)) { +#if PHP_VERSION_ID >= 80200 + zend_string *errstr; + auto size = zend_ini_parse_quantity(Z_STR_P(zv), &errstr); + if (errstr) { + php_swoole_fatal_error( + E_ERROR, "failed to parse '%s' to size, Error: %s", Z_STRVAL_P(zv), ZSTR_VAL(errstr)); + zend_string_release(errstr); + } + return size; +#else return zend_atol(Z_STRVAL_P(zv), Z_STRLEN_P(zv)); +#endif } else { return zval_get_long(zv); } @@ -979,6 +990,12 @@ const swoole::Allocator *sw_zend_string_allocator() { return &zend_string_allocator; } +static void sw_after_fork(void *args) { +#ifdef ZEND_MAX_EXECUTION_TIMERS + zend_max_execution_timer_init(); +#endif +} + PHP_RINIT_FUNCTION(swoole) { if (!SWOOLE_G(cli)) { return SUCCESS; @@ -1019,6 +1036,7 @@ PHP_RINIT_FUNCTION(swoole) { /* Disable warning even in ZEND_DEBUG because we may register our own signal handlers */ SIGG(check) = 0; #endif + swoole_add_hook(SW_GLOBAL_HOOK_AFTER_FORK, sw_after_fork, 0); php_swoole_http_server_rinit(); php_swoole_coroutine_rinit(); @@ -1041,8 +1059,6 @@ PHP_RSHUTDOWN_FUNCTION(swoole) { rshutdown_callbacks.execute(); - swoole_event_free(); - php_swoole_server_rshutdown(); php_swoole_http_server_rshutdown(); php_swoole_async_coro_rshutdown(); @@ -1052,6 +1068,8 @@ PHP_RSHUTDOWN_FUNCTION(swoole) { php_swoole_runtime_rshutdown(); php_swoole_process_rshutdown(); + swoole_event_free(); + SwooleG.running = 0; SWOOLE_G(req_status) = PHP_SWOOLE_RSHUTDOWN_END; diff --git a/ext-src/php_swoole_odbc.h b/ext-src/php_swoole_odbc.h index 8c4f6d989c0..e20be99b304 100644 --- a/ext-src/php_swoole_odbc.h +++ b/ext-src/php_swoole_odbc.h @@ -24,10 +24,14 @@ BEGIN_EXTERN_C() #include "ext/pdo/php_pdo_driver.h" -#if PHP_VERSION_ID > 80100 -#include "thirdparty/php81/pdo_odbc/php_pdo_odbc_int.h" -#else +#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100 #include "thirdparty/php80/pdo_odbc/php_pdo_odbc_int.h" +#elif PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200 +#include "thirdparty/php81/pdo_odbc/php_pdo_odbc_int.h" +#elif PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80300 +#include "thirdparty/php81/pdo_odbc/php_pdo_odbc_int.h" +#elif PHP_VERSION_ID >= 80300 +#include "thirdparty/php83/pdo_odbc/php_pdo_odbc_int.h" #endif extern const pdo_driver_t swoole_pdo_odbc_driver; diff --git a/ext-src/php_swoole_oracle.h b/ext-src/php_swoole_oracle.h index a2f0a3212e7..43b090d929f 100644 --- a/ext-src/php_swoole_oracle.h +++ b/ext-src/php_swoole_oracle.h @@ -25,10 +25,15 @@ BEGIN_EXTERN_C() #include "ext/pdo/php_pdo_driver.h" -#if PHP_VERSION_ID >= 80100 -#include "thirdparty/php81/pdo_oci/php_pdo_oci_int.h" -#else + +#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100 #include "thirdparty/php80/pdo_oci/php_pdo_oci_int.h" +#elif PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200 +#include "thirdparty/php81/pdo_oci/php_pdo_oci_int.h" +#elif PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80300 +#include "thirdparty/php81/pdo_oci/php_pdo_oci_int.h" +#elif PHP_VERSION_ID >= 80300 +#include "thirdparty/php83/pdo_oci/php_pdo_oci_int.h" #endif extern const pdo_driver_t swoole_pdo_oci_driver; diff --git a/ext-src/php_swoole_pgsql.h b/ext-src/php_swoole_pgsql.h index cdd267f020b..1606f672077 100644 --- a/ext-src/php_swoole_pgsql.h +++ b/ext-src/php_swoole_pgsql.h @@ -25,6 +25,16 @@ BEGIN_EXTERN_C() #include "ext/pdo/php_pdo_driver.h" +#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100 +#include "thirdparty/php80/pdo_pgsql/php_pdo_pgsql_int.h" +#elif PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200 +#include "thirdparty/php81/pdo_pgsql/php_pdo_pgsql_int.h" +#elif PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80300 +#include "thirdparty/php81/pdo_pgsql/php_pdo_pgsql_int.h" +#elif PHP_VERSION_ID >= 80300 +#include "thirdparty/php83/pdo_pgsql/php_pdo_pgsql_int.h" +#endif + extern const pdo_driver_t swoole_pdo_pgsql_driver; #include diff --git a/ext-src/php_swoole_sqlite.h b/ext-src/php_swoole_sqlite.h index ca942270c4b..e14b4e9b1aa 100644 --- a/ext-src/php_swoole_sqlite.h +++ b/ext-src/php_swoole_sqlite.h @@ -24,10 +24,15 @@ BEGIN_EXTERN_C() #include "ext/pdo/php_pdo_driver.h" -#if PHP_VERSION_ID >= 80100 -#include "thirdparty/php81/pdo_sqlite/php_pdo_sqlite_int.h" -#else + +#if PHP_VERSION_ID >= 80000 && PHP_VERSION_ID < 80100 #include "thirdparty/php80/pdo_sqlite/php_pdo_sqlite_int.h" +#elif PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80200 +#include "thirdparty/php81/pdo_sqlite/php_pdo_sqlite_int.h" +#elif PHP_VERSION_ID >= 80200 && PHP_VERSION_ID < 80300 +#include "thirdparty/php81/pdo_sqlite/php_pdo_sqlite_int.h" +#elif PHP_VERSION_ID >= 80300 +#include "thirdparty/php83/pdo_sqlite/php_pdo_sqlite_int.h" #endif extern const pdo_driver_t swoole_pdo_sqlite_driver; diff --git a/ext-src/swoole_coroutine.cc b/ext-src/swoole_coroutine.cc index e0e9d27799b..d20378f14d3 100644 --- a/ext-src/swoole_coroutine.cc +++ b/ext-src/swoole_coroutine.cc @@ -72,9 +72,8 @@ std::thread PHPCoroutine::interrupt_thread; bool PHPCoroutine::interrupt_thread_running = false; extern void php_swoole_load_library(); - -static zend_atomic_bool *zend_vm_interrupt = nullptr; static user_opcode_handler_t ori_exit_handler = nullptr; +static zend_atomic_bool *zend_vm_interrupt = nullptr; static user_opcode_handler_t ori_begin_silence_handler = nullptr; static user_opcode_handler_t ori_end_silence_handler = nullptr; static unordered_map user_yield_coros; @@ -385,6 +384,10 @@ void PHPCoroutine::activate() { } void PHPCoroutine::deactivate(void *ptr) { + if (sw_unlikely(!activated)) { + return; + } + activated = false; interrupt_thread_stop(); /** * reset runtime hook @@ -403,10 +406,12 @@ void PHPCoroutine::deactivate(void *ptr) { enable_unsafe_function(); Coroutine::deactivate(); - activated = false; } void PHPCoroutine::shutdown() { + if (activated) { + deactivate(nullptr); + } interrupt_thread_stop(); Coroutine::bailout(nullptr); if (options) { @@ -858,32 +863,30 @@ void PHPCoroutine::fiber_context_switch_try_notify(PHPContext *from, PHPContext #endif /* SWOOLE_COROUTINE_MOCK_FIBER_CONTEXT */ #ifdef ZEND_CHECK_STACK_LIMIT -void* PHPCoroutine::stack_limit(PHPContext *ctx) -{ +void *PHPCoroutine::stack_limit(PHPContext *ctx) { #ifdef SW_USE_THREAD_CONTEXT return nullptr; #else - zend_ulong reserve = EG(reserved_stack_size); + zend_ulong reserve = EG(reserved_stack_size); #ifdef __APPLE__ - /* On Apple Clang, the stack probing function ___chkstk_darwin incorrectly - * probes a location that is twice the entered function's stack usage away - * from the stack pointer, when using an alternative stack. - * https://openradar.appspot.com/radar?id=5497722702397440 - */ - reserve = reserve * 2; + /* On Apple Clang, the stack probing function ___chkstk_darwin incorrectly + * probes a location that is twice the entered function's stack usage away + * from the stack pointer, when using an alternative stack. + * https://openradar.appspot.com/radar?id=5497722702397440 + */ + reserve = reserve * 2; #endif if (!ctx->co) { return nullptr; } - /* stack->pointer is the end of the stack */ - return (int8_t*)ctx->co->get_ctx().get_stack() + reserve; + /* stack->pointer is the end of the stack */ + return (int8_t *) ctx->co->get_ctx().get_stack() + reserve; #endif } -void* PHPCoroutine::stack_base(PHPContext *ctx) -{ +void *PHPCoroutine::stack_base(PHPContext *ctx) { #ifdef SW_USE_THREAD_CONTEXT return nullptr; #else @@ -891,7 +894,7 @@ void* PHPCoroutine::stack_base(PHPContext *ctx) return nullptr; } - return (void*)((uintptr_t)ctx->co->get_ctx().get_stack() + ctx->co->get_ctx().get_stack_size()); + return (void *) ((uintptr_t) ctx->co->get_ctx().get_stack() + ctx->co->get_ctx().get_stack_size()); #endif } #endif /* ZEND_CHECK_STACK_LIMIT */ @@ -910,8 +913,7 @@ struct AutoloadQueue { std::queue *queue; }; -static zend_class_entry *swoole_coroutine_autoload(zend_string *name, zend_string *lc_name) -{ +static zend_class_entry *swoole_coroutine_autoload(zend_string *name, zend_string *lc_name) { auto current = Coroutine::get_current(); if (!current) { return original_zend_autoload(name, lc_name); diff --git a/ext-src/swoole_http2_client_coro.cc b/ext-src/swoole_http2_client_coro.cc index 1c182f19c29..f94e767baa6 100644 --- a/ext-src/swoole_http2_client_coro.cc +++ b/ext-src/swoole_http2_client_coro.cc @@ -349,6 +349,7 @@ void php_swoole_http2_client_coro_minit(int module_number) { zend_declare_property_bool(swoole_http2_request_ce, ZEND_STRL("usePipelineRead"), 0, ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_http2_response_ce, ZEND_STRL("streamId"), 0, ZEND_ACC_PUBLIC); + zend_declare_property_long(swoole_http2_response_ce, ZEND_STRL("serverLastStreamId"), 0, ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_http2_response_ce, ZEND_STRL("errCode"), 0, ZEND_ACC_PUBLIC); zend_declare_property_long(swoole_http2_response_ce, ZEND_STRL("statusCode"), 0, ZEND_ACC_PUBLIC); zend_declare_property_bool(swoole_http2_response_ce, ZEND_STRL("pipeline"), 0, ZEND_ACC_PUBLIC); diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 4746b332bf6..e79a7aa613d 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -93,7 +93,8 @@ class Client { #ifdef SW_USE_OPENSSL uint8_t ssl; #endif - double connect_timeout = network::Socket::default_connect_timeout; + double connect_timeout = 0; + double response_timeout = 0; bool defer = false; bool lowercase_header = true; bool use_default_port; @@ -706,10 +707,12 @@ void Client::apply_setting(zval *zset, const bool check_all) { zval *ztmp; HashTable *vht = Z_ARRVAL_P(zset); - if (php_swoole_array_get_value(vht, "connect_timeout", ztmp) || - php_swoole_array_get_value(vht, "timeout", ztmp) /* backward compatibility */) { + if (php_swoole_array_get_value(vht, "connect_timeout", ztmp)) { connect_timeout = zval_get_double(ztmp); } + if (php_swoole_array_get_value(vht, "timeout", ztmp)) { + response_timeout = zval_get_double(ztmp); + } if (php_swoole_array_get_value(vht, "max_retries", ztmp)) { max_retries = (uint8_t) SW_MIN(zval_get_long(ztmp), UINT8_MAX); } @@ -806,11 +809,11 @@ bool Client::connect() { accept_websocket_compression = false; #endif - // socket->set_buffer_allocator(&SWOOLE_G(zend_string_allocator)); - // connect - socket->set_timeout(connect_timeout, Socket::TIMEOUT_CONNECT); + double _timeout = connect_timeout == 0 ? network::Socket::default_connect_timeout : connect_timeout; + socket->set_timeout(_timeout, Socket::TIMEOUT_CONNECT); socket->set_resolve_context(&resolve_context_); socket->set_dtor([this](Socket *_socket) { socket_dtor(); }); + // socket->set_buffer_allocator(&SWOOLE_G(zend_string_allocator)); if (!socket->connect(host, port)) { set_error(socket->errCode, socket->errMsg, ESTATUS_CONNECT_FAILED); @@ -1368,9 +1371,9 @@ bool Client::recv_response(double timeout) { parser.data = this; if (timeout == 0) { - timeout = socket->get_timeout(Socket::TIMEOUT_READ); + timeout = response_timeout == 0 ? network::Socket::default_read_timeout : response_timeout; } - Socket::timeout_controller tc(socket, timeout, Socket::TIMEOUT_READ); + Socket::TimeoutController tc(socket, timeout, Socket::TIMEOUT_READ); bool success = false; while (true) { if (sw_unlikely(tc.has_timedout(Socket::TIMEOUT_READ))) { diff --git a/ext-src/swoole_http_request.cc b/ext-src/swoole_http_request.cc index 658a34d303f..371fe0d7bdc 100644 --- a/ext-src/swoole_http_request.cc +++ b/ext-src/swoole_http_request.cc @@ -845,10 +845,6 @@ const char *HttpContext::get_content_encoding() { } #endif -static void swoole_request_read_fd_property(zend_object *object, HttpContext *ctx) { - zend_update_property_long(swoole_http_request_ce, object, ZEND_STRL("fd"), ctx->fd); -} - static PHP_METHOD(swoole_http_request, getContent) { HttpContext *ctx = php_swoole_http_request_get_and_check_context(ZEND_THIS); if (UNEXPECTED(!ctx)) { diff --git a/ext-src/swoole_http_response.cc b/ext-src/swoole_http_response.cc index d4a663f5580..6c2e49d303d 100644 --- a/ext-src/swoole_http_response.cc +++ b/ext-src/swoole_http_response.cc @@ -746,6 +746,7 @@ bool HttpContext::send_file(const char *file, uint32_t l_file, off_t offset, siz void HttpContext::end(zval *zdata, zval *return_value) { char *data = nullptr; size_t length = zdata ? php_swoole_get_send_data(zdata, &data) : 0; + String *http_buffer = nullptr; if (send_chunked) { if (send_trailer_) { @@ -760,7 +761,7 @@ void HttpContext::end(zval *zdata, zval *return_value) { } } send_chunked = 0; - return; + goto _skip_copy; } #ifdef SW_HAVE_ZLIB @@ -790,7 +791,7 @@ void HttpContext::end(zval *zdata, zval *return_value) { } #endif - String *http_buffer = get_write_buffer(); + http_buffer = get_write_buffer(); http_buffer->clear(); build_header(http_buffer, data, length); diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index bca5454c9d7..b60723e1e6c 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -394,10 +394,15 @@ bool swoole_http_server_onBeforeRequest(HttpContext *ctx) { ctx->onBeforeRequest = nullptr; ctx->onAfterResponse = swoole_http_server_onAfterResponse; Server *serv = (Server *) ctx->private_data; - SwooleWG.worker->concurrency++; - sw_atomic_add_fetch(&serv->gs->concurrency, 1); + if (!sw_server() || !sw_worker() || sw_worker()->is_shutdown()) { + return false; + } + + auto worker = sw_worker(); swoole_trace("serv->gs->concurrency=%u, max_concurrency=%u", serv->gs->concurrency, serv->gs->max_concurrency); - if (SwooleWG.worker->concurrency > serv->worker_max_concurrency) { + sw_atomic_add_fetch(&serv->gs->concurrency, 1); + worker->concurrency++; + if (worker->concurrency > serv->worker_max_concurrency) { swoole_trace_log(SW_TRACE_COROUTINE, "exceed worker_max_concurrency[%u] limit, request[%p] queued", serv->worker_max_concurrency, @@ -412,13 +417,18 @@ bool swoole_http_server_onBeforeRequest(HttpContext *ctx) { void swoole_http_server_onAfterResponse(HttpContext *ctx) { ctx->onAfterResponse = nullptr; Server *serv = (Server *) ctx->private_data; - SwooleWG.worker->concurrency--; - sw_atomic_sub_fetch(&serv->gs->concurrency, 1); + if (!sw_server() || !sw_worker() || sw_worker()->is_shutdown()) { + return; + } + + auto worker = sw_worker(); swoole_trace("serv->gs->concurrency=%u, max_concurrency=%u", serv->gs->concurrency, serv->gs->max_concurrency); + sw_atomic_sub_fetch(&serv->gs->concurrency, 1); + worker->concurrency--; + if (!queued_http_contexts.empty()) { HttpContext *ctx = queued_http_contexts.front(); - swoole_trace( - "[POP 1] concurrency=%u, ctx=%p, request=%p", SwooleWG.worker->concurrency, ctx, ctx->request.zobject); + swoole_trace("[POP 1] concurrency=%u, ctx=%p, request=%p", worker->concurrency, ctx, ctx->request.zobject); queued_http_contexts.pop(); swoole_event_defer( [](void *private_data) { diff --git a/ext-src/swoole_mysql_coro.cc b/ext-src/swoole_mysql_coro.cc index c388de802b1..f09acdd1286 100644 --- a/ext-src/swoole_mysql_coro.cc +++ b/ext-src/swoole_mysql_coro.cc @@ -26,6 +26,7 @@ #undef L64 SW_EXTERN_C_BEGIN + #include "ext/hash/php_hash.h" #include "ext/hash/php_hash_sha.h" #include "ext/standard/php_math.h" @@ -64,7 +65,7 @@ class MysqlClient { Socket *socket = nullptr; zval zsocket; zval zobject; - Socket::timeout_controller *tc = nullptr; + Socket::TimeoutController *tc = nullptr; enum sw_mysql_state state = SW_MYSQL_STATE_CLOSED; bool quit = false; @@ -173,7 +174,7 @@ class MysqlClient { // Notice: `timeout > 0` is wrong, maybe -1 if (timeout != 0) { SW_ASSERT(!tc); - tc = new Socket::timeout_controller(socket, timeout, type); + tc = new Socket::TimeoutController(socket, timeout, type); } } diff --git a/ext-src/swoole_oracle.cc b/ext-src/swoole_oracle.cc index af7d90e4e92..ace8dc584fb 100644 --- a/ext-src/swoole_oracle.cc +++ b/ext-src/swoole_oracle.cc @@ -22,8 +22,6 @@ #ifdef SW_USE_ORACLE -using swoole::Coroutine; - static bool swoole_oracle_blocking = true; void swoole_oracle_set_blocking(bool blocking) { swoole_oracle_blocking = blocking; @@ -49,7 +47,8 @@ sword swoole_oci_stmt_prepare( OCIStmt *stmtp, OCIError *errhp, const OraText *stmt, ub4 stmt_len, ub4 language, ub4 mode) { swoole_trace_log(SW_TRACE_CO_ORACLE, "oci_stmt_prepare"); sword result = 0; - php_swoole_async(swoole_oracle_blocking, [&]() { result = OCIStmtPrepare(stmtp, errhp, stmt, stmt_len, language, mode); }); + php_swoole_async(swoole_oracle_blocking, + [&]() { result = OCIStmtPrepare(stmtp, errhp, stmt, stmt_len, language, mode); }); return result; } @@ -64,7 +63,8 @@ sword swoole_oci_stmt_execute(OCISvcCtx *svchp, ub4 mode) { swoole_trace_log(SW_TRACE_CO_ORACLE, "oci_stmt_execute"); sword result = 0; - php_swoole_async(swoole_oracle_blocking, [&]() { result = OCIStmtExecute(svchp, stmtp, errhp, iters, rowoff, snap_in, snap_out, mode); }); + php_swoole_async(swoole_oracle_blocking, + [&]() { result = OCIStmtExecute(svchp, stmtp, errhp, iters, rowoff, snap_in, snap_out, mode); }); return result; } @@ -80,7 +80,8 @@ sword swoole_oci_stmt_fetch(OCIStmt *stmtp, OCIError *errhp, ub4 nrows, ub2 orie sword swoole_oci_stmt_fetch2(OCIStmt *stmtp, OCIError *errhp, ub4 nrows, ub2 orientation, sb4 scrollOffset, ub4 mode) { swoole_trace_log(SW_TRACE_CO_ORACLE, "oci_stmt_fetch2"); sword result = 0; - php_swoole_async(swoole_oracle_blocking, [&]() { result = OCIStmtFetch2(stmtp, errhp, nrows, orientation, scrollOffset, mode); }); + php_swoole_async(swoole_oracle_blocking, + [&]() { result = OCIStmtFetch2(stmtp, errhp, nrows, orientation, scrollOffset, mode); }); return result; } diff --git a/ext-src/swoole_pgsql.cc b/ext-src/swoole_pgsql.cc index b8c08903a58..0e7016bf12a 100644 --- a/ext-src/swoole_pgsql.cc +++ b/ext-src/swoole_pgsql.cc @@ -22,19 +22,15 @@ #include "swoole_coroutine_system.h" #ifdef SW_USE_PGSQL -#if PHP_VERSION_ID > 80100 -#include "thirdparty/php81/pdo_pgsql/php_pdo_pgsql_int.h" -#else -#include "thirdparty/php80/pdo_pgsql/php_pdo_pgsql_int.h" -#endif +using swoole::Coroutine; using swoole::Reactor; using swoole::coroutine::Socket; using swoole::coroutine::translate_events_to_poll; static bool swoole_pgsql_blocking = true; -static int swoole_pgsql_socket_poll(PGconn *conn, swEventType event, double timeout = -1) { +static int swoole_pgsql_socket_poll(PGconn *conn, swEventType event, double timeout = -1, bool check_nonblock = false) { if (swoole_pgsql_blocking) { struct pollfd fds[1]; fds[0].fd = PQsocket(conn); @@ -42,7 +38,7 @@ static int swoole_pgsql_socket_poll(PGconn *conn, swEventType event, double time int result = 0; do { - result = poll(fds, 1, timeout); + result = poll(fds, 1, timeout); } while (result < 0 && errno == EINTR); return result > 0 ? 1 : errno == ETIMEDOUT ? 0 : -1; @@ -50,7 +46,19 @@ static int swoole_pgsql_socket_poll(PGconn *conn, swEventType event, double time Socket sock(PQsocket(conn), SW_SOCK_RAW); sock.get_socket()->nonblock = 1; + bool retval = sock.poll(event, timeout); + while (check_nonblock && event == SW_EVENT_READ) { + if (PQconsumeInput(conn) == 0) { + retval = false; + break; + } + if (PQisBusy(conn) == 0) { + break; + } + retval = sock.poll(event, timeout); + } + sock.move_fd(); return retval ? 1 : sock.errCode == ETIMEDOUT ? 0 : -1; } @@ -72,7 +80,8 @@ static int swoole_pgsql_flush(PGconn *conn) { static PGresult *swoole_pgsql_get_result(PGconn *conn) { PGresult *result, *last_result = nullptr; - int poll_ret = swoole_pgsql_socket_poll(conn, SW_EVENT_READ); + // PQgetResult will block the process; it is necessary to forcibly check if the data is ready. + int poll_ret = swoole_pgsql_socket_poll(conn, SW_EVENT_READ, -1, true); if (sw_unlikely(poll_ret == SW_ERR)) { return nullptr; } @@ -97,7 +106,11 @@ PGconn *swoole_pgsql_connectdb(const char *conninfo) { return conn; } - PQsetnonblocking(conn, 1); + if (!swoole_pgsql_blocking && Coroutine::get_current()) { + PQsetnonblocking(conn, 1); + } else { + PQsetnonblocking(conn, 0); + } SW_LOOP { int r = PQconnectPoll(conn); diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index a7856f401b4..c17e6685c98 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -163,6 +163,39 @@ static zend_internal_arg_info *get_arginfo(const char *name, size_t l_name) { return zf->internal_function.arg_info; } +static zend_internal_arg_info *copy_arginfo(zend_function *zf, zend_internal_arg_info *_arg_info) { + uint32_t num_args = zf->internal_function.num_args + 1; + zend_internal_arg_info *arg_info = _arg_info - 1; + + auto new_arg_info = (zend_internal_arg_info *) pemalloc(sizeof(zend_internal_arg_info) * num_args, 1); + memcpy(new_arg_info, arg_info, sizeof(zend_internal_arg_info) * num_args); + + if (zf->internal_function.fn_flags & ZEND_ACC_VARIADIC) { + num_args++; + } + + for (uint32_t i = 0; i < num_args; i++) { + if (ZEND_TYPE_HAS_LIST(arg_info[i].type)) { + zend_type_list *old_list = ZEND_TYPE_LIST(arg_info[i].type); + zend_type_list *new_list = (zend_type_list *) pemalloc(ZEND_TYPE_LIST_SIZE(old_list->num_types), 1); + memcpy(new_list, old_list, ZEND_TYPE_LIST_SIZE(old_list->num_types)); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, new_list); + + zend_type *list_type; + ZEND_TYPE_LIST_FOREACH(new_list, list_type) { + zend_string *name = zend_string_dup(ZEND_TYPE_NAME(*list_type), 1); + ZEND_TYPE_SET_PTR(*list_type, name); + } + ZEND_TYPE_LIST_FOREACH_END(); + } else if (ZEND_TYPE_HAS_NAME(arg_info[i].type)) { + zend_string *name = zend_string_dup(ZEND_TYPE_NAME(arg_info[i].type), 1); + ZEND_TYPE_SET_PTR(new_arg_info[i].type, name); + } + } + + return new_arg_info + 1; +} + #define SW_HOOK_FUNC(f) hook_func(ZEND_STRL(#f), PHP_FN(swoole_##f)) #define SW_UNHOOK_FUNC(f) unhook_func(ZEND_STRL(#f)) #define SW_HOOK_WITH_NATIVE_FUNC(f) \ @@ -224,6 +257,7 @@ struct real_func { zend_function *function; zif_handler ori_handler; zend_internal_arg_info *ori_arg_info; + zend_internal_arg_info *arg_info_copy; uint32_t ori_fn_flags; uint32_t ori_num_args; zend_fcall_info_cache *fci_cache; @@ -754,28 +788,25 @@ static int socket_enable_crypto(php_stream *stream, Socket *sock, php_stream_xpo php_stream_context *context = PHP_STREAM_CONTEXT(stream); if (cparam->inputs.activate && !sock->ssl_is_available()) { sock->enable_ssl_encrypt(); - if (!sock->ssl_check_context()) { - return -1; - } if (!socket_ssl_set_options(sock, context)) { return -1; } if (!sock->ssl_handshake()) { return -1; } - return 0; } else if (!cparam->inputs.activate && sock->ssl_is_available()) { - return sock->ssl_shutdown() ? 0 : -1; + sock->ssl_shutdown(); + return -1; } - if (context) { + if (context && sock->ssl_is_available()) { zval *val = php_stream_context_get_option(context, "ssl", "capture_peer_cert"); if (val && zend_is_true(val) && !php_openssl_capture_peer_certs(stream, sock)) { return -1; } } - return 0; + return 1; } #endif @@ -1030,11 +1061,9 @@ static bool socket_ssl_set_options(Socket *sock, php_stream_context *context) { add_alias("verify_depth", "ssl_verify_depth"); add_alias("disable_compression", "ssl_disable_compression"); - php_swoole_socket_set_ssl(sock, &zalias); - if (!sock->ssl_check_context()) { - return false; - } + bool ret = php_swoole_socket_set_ssl(sock, &zalias); zval_dtor(&zalias); + return ret; } #endif } @@ -1168,6 +1197,11 @@ void PHPCoroutine::enable_unsafe_function() { } } +static void hook_stream_throw_exception(const char *type) { + swoole_error_log( + SW_LOG_WARNING, SW_ERROR_PHP_FATAL_ERROR, "failed to register `%s` stream transport factory", type); +} + bool PHPCoroutine::enable_hook(uint32_t flags) { if (swoole_isset_hook((enum swGlobalHookType) PHP_SWOOLE_HOOK_BEFORE_ENABLE_HOOK)) { swoole_call_hook((enum swGlobalHookType) PHP_SWOOLE_HOOK_BEFORE_ENABLE_HOOK, &flags); @@ -1194,6 +1228,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_TCP)) { if (php_stream_xport_register("tcp", socket_create) != SUCCESS) { flags ^= PHPCoroutine::HOOK_TCP; + hook_stream_throw_exception("tcp"); } } } else { @@ -1205,6 +1240,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_UDP)) { if (php_stream_xport_register("udp", socket_create) != SUCCESS) { flags ^= PHPCoroutine::HOOK_UDP; + hook_stream_throw_exception("udp"); } } } else { @@ -1216,6 +1252,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_UNIX)) { if (php_stream_xport_register("unix", socket_create) != SUCCESS) { flags ^= PHPCoroutine::HOOK_UNIX; + hook_stream_throw_exception("unix"); } } } else { @@ -1227,6 +1264,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_UDG)) { if (php_stream_xport_register("udg", socket_create) != SUCCESS) { flags ^= PHPCoroutine::HOOK_UDG; + hook_stream_throw_exception("udg"); } } } else { @@ -1238,6 +1276,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_SSL)) { if (php_stream_xport_register("ssl", socket_create) != SUCCESS) { flags ^= PHPCoroutine::HOOK_SSL; + hook_stream_throw_exception("ssl"); } } } else { @@ -1253,6 +1292,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_TLS)) { if (php_stream_xport_register("tls", socket_create) != SUCCESS) { flags ^= PHPCoroutine::HOOK_TLS; + hook_stream_throw_exception("tls"); } } } else { @@ -1375,8 +1415,8 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { if (flags & PHPCoroutine::HOOK_BLOCKING_FUNCTION) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_BLOCKING_FUNCTION)) { hook_func(ZEND_STRL("gethostbyname"), PHP_FN(swoole_coroutine_gethostbyname)); - hook_func(ZEND_STRL("exec")); - hook_func(ZEND_STRL("shell_exec")); + SW_HOOK_WITH_PHP_FUNC(exec); + SW_HOOK_WITH_PHP_FUNC(shell_exec); } } else { if (runtime_hook_flags & PHPCoroutine::HOOK_BLOCKING_FUNCTION) { @@ -1385,6 +1425,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { SW_UNHOOK_FUNC(shell_exec); } } + // ext-sockets if (flags & PHPCoroutine::HOOK_SOCKETS) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_SOCKETS)) { SW_HOOK_WITH_PHP_FUNC(socket_create); @@ -1450,6 +1491,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { } #ifdef SW_USE_CURL + // curl native if (flags & PHPCoroutine::HOOK_NATIVE_CURL) { if (flags & PHPCoroutine::HOOK_CURL) { php_swoole_fatal_error(E_WARNING, "cannot enable both hooks HOOK_NATIVE_CURL and HOOK_CURL at same time"); @@ -1510,7 +1552,7 @@ bool PHPCoroutine::enable_hook(uint32_t flags) { } } #endif - + // curl if (flags & PHPCoroutine::HOOK_CURL) { if (!(runtime_hook_flags & PHPCoroutine::HOOK_CURL)) { SW_HOOK_WITH_PHP_FUNC(curl_init); @@ -1953,7 +1995,8 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend rf->ori_arg_info = zf->internal_function.arg_info; zf->internal_function.handler = handler; if (arg_info) { - zf->internal_function.arg_info = arg_info; + zf->internal_function.arg_info = copy_arginfo(zf, arg_info); + rf->arg_info_copy = zf->internal_function.arg_info; } if (use_php_func) { @@ -1981,6 +2024,10 @@ static void unhook_func(const char *name, size_t l_name) { if (rf == nullptr) { return; } + if (rf->arg_info_copy) { + zend_free_internal_arg_info(&rf->function->internal_function); + rf->arg_info_copy = nullptr; + } rf->function->internal_function.handler = rf->ori_handler; rf->function->internal_function.arg_info = rf->ori_arg_info; } diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 879a6ac1793..d52bc4ca85e 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -99,6 +99,10 @@ void php_swoole_server_rshutdown() { serv->drain_worker_pipe(); if (serv->is_started() && !serv->is_user_worker()) { + sw_worker()->shutdown(); + if (serv->is_event_worker()) { + serv->clean_worker_connections(sw_worker()); + } if (php_swoole_is_fatal_error()) { swoole_error_log(SW_LOG_ERROR, SW_ERROR_PHP_FATAL_ERROR, @@ -1511,10 +1515,9 @@ static void php_swoole_server_onAfterReload(Server *serv) { } static void php_swoole_server_onWorkerStop(Server *serv, Worker *worker) { - if (SwooleWG.shutdown) { + if (!SwooleWG.running) { return; } - SwooleWG.shutdown = true; zval *zserv = (zval *) serv->private_data_2; ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); @@ -2813,6 +2816,7 @@ static PHP_METHOD(swoole_server, stats) { add_assoc_long_ex(return_value, ZEND_STRL("total_recv_bytes"), serv->gs->total_recv_bytes); add_assoc_long_ex(return_value, ZEND_STRL("total_send_bytes"), serv->gs->total_send_bytes); add_assoc_long_ex(return_value, ZEND_STRL("pipe_packet_msg_id"), serv->gs->pipe_packet_msg_id); + add_assoc_long_ex(return_value, ZEND_STRL("concurrency"), serv->get_concurrency()); add_assoc_long_ex(return_value, ZEND_STRL("session_round"), serv->gs->session_round); add_assoc_long_ex(return_value, ZEND_STRL("min_fd"), serv->gs->min_fd); add_assoc_long_ex(return_value, ZEND_STRL("max_fd"), serv->gs->max_fd); @@ -2821,6 +2825,7 @@ static PHP_METHOD(swoole_server, stats) { add_assoc_long_ex(return_value, ZEND_STRL("worker_request_count"), SwooleWG.worker->request_count); add_assoc_long_ex(return_value, ZEND_STRL("worker_response_count"), SwooleWG.worker->response_count); add_assoc_long_ex(return_value, ZEND_STRL("worker_dispatch_count"), SwooleWG.worker->dispatch_count); + add_assoc_long_ex(return_value, ZEND_STRL("worker_concurrency"), SwooleWG.worker->concurrency); } if (serv->task_ipc_mode > Server::TASK_IPC_UNIXSOCK && serv->gs->task_workers.queue) { @@ -3804,7 +3809,7 @@ static PHP_METHOD(swoole_server, stop) { } zend_bool wait_reactor = 0; - zend_long worker_id = SwooleG.process_id; + zend_long worker_id = -1; ZEND_PARSE_PARAMETERS_START(0, 2) Z_PARAM_OPTIONAL @@ -3812,6 +3817,7 @@ static PHP_METHOD(swoole_server, stop) { Z_PARAM_BOOL(wait_reactor) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); + worker_id = worker_id < 0 ? SwooleG.process_id : worker_id; if (worker_id == SwooleG.process_id && wait_reactor == 0) { if (SwooleTG.reactor != nullptr) { SwooleTG.reactor->defer( diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index a78ece50e3d..bb42ee32726 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -1133,7 +1133,6 @@ SW_API bool php_swoole_socket_set(Socket *cli, zval *zset) { SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) { HashTable *vht = Z_ARRVAL_P(zset); zval *ztmp; - bool ret = true; if (php_swoole_array_get_value(vht, "ssl_protocols", ztmp)) { zend_long v = zval_get_long(ztmp); @@ -1150,7 +1149,7 @@ SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) { sock->get_ssl_context()->cert_file = str_v.to_std_string(); } else { php_swoole_fatal_error(E_WARNING, "ssl cert file[%s] not found", str_v.val()); - ret = false; + return false; } } if (php_swoole_array_get_value(vht, "ssl_key_file", ztmp)) { @@ -1159,7 +1158,7 @@ SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) { sock->get_ssl_context()->key_file = str_v.to_std_string(); } else { php_swoole_fatal_error(E_WARNING, "ssl key file[%s] not found", str_v.val()); - ret = false; + return false; } } if (!sock->get_ssl_context()->cert_file.empty() && sock->get_ssl_context()->key_file.empty()) { @@ -1206,11 +1205,7 @@ SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) { sock->get_ssl_context()->grease = SW_MAX(0, SW_MIN(v, UINT8_MAX)); } #endif - - if (!sock->ssl_check_context()) { - ret = false; - } - return ret; + return true; } #endif diff --git a/ext-src/swoole_table.cc b/ext-src/swoole_table.cc index 585faa63839..a8ac8d624e7 100644 --- a/ext-src/swoole_table.cc +++ b/ext-src/swoole_table.cc @@ -110,10 +110,6 @@ static void inline php_swoole_table_set_ptr(zval *zobject, Table *ptr) { } static inline void php_swoole_table_free_object(zend_object *object) { - Table *table = php_swoole_table_fetch_object(object)->ptr; - if (table) { - table->free(); - } zend_object_std_dtor(object); } diff --git a/include/swoole.h b/include/swoole.h index ed1a834a76e..c1e5d6eb096 100644 --- a/include/swoole.h +++ b/include/swoole.h @@ -513,17 +513,13 @@ enum swDNSLookupFlag { SW_DNS_LOOKUP_RANDOM = (1u << 11), }; -#ifdef __MACH__ -char *sw_error_(); -#define sw_error sw_error_() -#else -extern __thread char sw_error[SW_ERROR_MSG_SIZE]; -#endif +extern thread_local char sw_error[SW_ERROR_MSG_SIZE]; enum swProcessType { SW_PROCESS_MASTER = 1, SW_PROCESS_WORKER = 2, SW_PROCESS_MANAGER = 3, + SW_PROCESS_EVENTWORKER = 2, SW_PROCESS_TASKWORKER = 4, SW_PROCESS_USERWORKER = 5, }; @@ -753,7 +749,7 @@ double microtime(void); } // namespace swoole extern swoole::Global SwooleG; // Local Global Variable -extern __thread swoole::ThreadGlobal SwooleTG; // Thread Global Variable +extern thread_local swoole::ThreadGlobal SwooleTG; // Thread Global Variable #define SW_CPU_NUM (SwooleG.cpu_num) diff --git a/include/swoole_async.h b/include/swoole_async.h index f5c718d2c0d..3ab5f5c745c 100644 --- a/include/swoole_async.h +++ b/include/swoole_async.h @@ -34,13 +34,17 @@ enum AsyncFlag { SW_AIO_EOF = 1u << 2, }; +struct AsyncRequest { + virtual ~AsyncRequest() = default; +}; + struct AsyncEvent { size_t task_id; uint8_t canceled; /** * input & output */ - void *data; + std::shared_ptr data; /** * output */ @@ -60,22 +64,44 @@ struct AsyncEvent { } }; -struct GethostbynameRequest { - const char *name; +struct GethostbynameRequest : public AsyncRequest { + std::string name; int family; char *addr; size_t addr_len; - GethostbynameRequest(const char *_name, int _family) : name(_name), family(_family) { + GethostbynameRequest(std::string _name, int _family) : name(std::move(_name)), family(_family) { addr_len = _family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN; addr = new char[addr_len]; } - ~GethostbynameRequest() { + ~GethostbynameRequest() override { delete[] addr; } }; +struct GetaddrinfoRequest : public AsyncRequest { + std::string hostname; + std::string service; + int family; + int socktype; + int protocol; + int error; + std::vector results; + int count; + void parse_result(std::vector &retval); + GetaddrinfoRequest(std::string _hostname, int _family, int _socktype, int _protocol, std::string _service) + : hostname(std::move(_hostname)), + service(std::move(_service)) { + family =_family; + socktype =_socktype; + protocol =_protocol; + count = 0; + error = 0; + } + ~GetaddrinfoRequest() override = default; +}; + class AsyncThreads { public: bool schedule = false; diff --git a/include/swoole_atomic.h b/include/swoole_atomic.h index adead3cd1f2..8b7b1b50008 100644 --- a/include/swoole_atomic.h +++ b/include/swoole_atomic.h @@ -27,6 +27,7 @@ typedef sw_atomic_uint64_t sw_atomic_ulong_t; typedef sw_atomic_uint32_t sw_atomic_t; #define sw_atomic_cmp_set(lock, old, set) __sync_bool_compare_and_swap(lock, old, set) +#define sw_atomic_value_cmp_set(value, expected, set) __sync_val_compare_and_swap(value, expected, set) #define sw_atomic_fetch_add(value, add) __sync_fetch_and_add(value, add) #define sw_atomic_fetch_sub(value, sub) __sync_fetch_and_sub(value, sub) #define sw_atomic_memory_barrier() __sync_synchronize() diff --git a/include/swoole_c_api.h b/include/swoole_c_api.h index 28e27839068..37c1211d56c 100644 --- a/include/swoole_c_api.h +++ b/include/swoole_c_api.h @@ -39,6 +39,7 @@ enum swGlobalHookType { SW_GLOBAL_HOOK_ON_REACTOR_DESTROY, SW_GLOBAL_HOOK_BEFORE_SERVER_CREATE, SW_GLOBAL_HOOK_AFTER_SERVER_CREATE, + SW_GLOBAL_HOOK_AFTER_FORK, SW_GLOBAL_HOOK_USER = 24, SW_GLOBAL_HOOK_END = SW_MAX_HOOK_TYPE - 1, }; diff --git a/include/swoole_coroutine_socket.h b/include/swoole_coroutine_socket.h index d22937fb807..f5415b0631b 100644 --- a/include/swoole_coroutine_socket.h +++ b/include/swoole_coroutine_socket.h @@ -148,7 +148,6 @@ class Socket { return ssl_context.get(); } - bool ssl_check_context(); bool ssl_handshake(); bool ssl_verify(bool allow_self_signed); std::string ssl_get_peer_cert(); @@ -442,7 +441,9 @@ class Socket { bool ssl_handshaked = false; std::shared_ptr ssl_context = nullptr; std::string ssl_host_name; + bool ssl_context_create(); bool ssl_create(SSLContext *ssl_context); + bool ssl_listen(); #endif bool connected = false; @@ -511,8 +512,8 @@ class Socket { class TimerController { public: - TimerController(TimerNode **timer_pp, double timeout, Socket *sock, TimerCallback callback) - : timer_pp(timer_pp), timeout(timeout), socket_(sock), callback(callback) {} + TimerController(TimerNode **_timer_pp, double _timeout, Socket *_socket, TimerCallback _callback) + : timer_pp(_timer_pp), timeout(_timeout), socket_(_socket), callback(std::move(_callback)) {} bool start() { if (timeout != 0 && !*timer_pp) { enabled = true; @@ -544,16 +545,16 @@ class Socket { public: class TimeoutSetter { public: - TimeoutSetter(Socket *socket, double timeout, const enum TimeoutType type) - : socket_(socket), timeout(timeout), type(type) { - if (timeout == 0) { + TimeoutSetter(Socket *socket, double _timeout, const enum TimeoutType _type) + : socket_(socket), timeout(_timeout), type(_type) { + if (_timeout == 0) { return; } for (uint8_t i = 0; i < SW_ARRAY_SIZE(timeout_type_list); i++) { - if (type & timeout_type_list[i]) { + if (_type & timeout_type_list[i]) { original_timeout[i] = socket->get_timeout(timeout_type_list[i]); - if (timeout != original_timeout[i]) { - socket->set_timeout(timeout, timeout_type_list[i]); + if (_timeout != original_timeout[i]) { + socket->set_timeout(_timeout, timeout_type_list[i]); } } } @@ -578,12 +579,13 @@ class Socket { double original_timeout[sizeof(timeout_type_list)] = {}; }; - class timeout_controller : public TimeoutSetter { + class TimeoutController : public TimeoutSetter { public: - timeout_controller(Socket *socket, double timeout, const enum TimeoutType type) - : TimeoutSetter(socket, timeout, type) {} - bool has_timedout(const enum TimeoutType type) { - SW_ASSERT_1BYTE(type); + TimeoutController(Socket *_socket, double _timeout, const enum TimeoutType _type) + : TimeoutSetter(_socket, _timeout, _type) {} + + bool has_timedout(const enum TimeoutType _type) { + SW_ASSERT_1BYTE(_type); if (timeout > 0) { if (sw_unlikely(startup_time == 0)) { startup_time = microtime(); @@ -593,7 +595,7 @@ class Socket { socket_->set_err(ETIMEDOUT); return true; } - socket_->set_timeout(timeout - used_time, type); + socket_->set_timeout(timeout - used_time, _type); } } return false; diff --git a/include/swoole_error.h b/include/swoole_error.h index 603d0cd38bc..8230c9fde0e 100644 --- a/include/swoole_error.h +++ b/include/swoole_error.h @@ -73,6 +73,7 @@ enum swErrorCode { SW_ERROR_SSL_BAD_PROTOCOL, SW_ERROR_SSL_RESET, SW_ERROR_SSL_HANDSHAKE_FAILED, + SW_ERROR_SSL_CREATE_CONTEXT_FAILED, SW_ERROR_PACKAGE_LENGTH_TOO_LARGE = 1201, SW_ERROR_PACKAGE_LENGTH_NOT_FOUND, diff --git a/include/swoole_process_pool.h b/include/swoole_process_pool.h index cf6fc72f289..d0a387a9b7a 100644 --- a/include/swoole_process_pool.h +++ b/include/swoole_process_pool.h @@ -103,10 +103,21 @@ struct ProcessPool; struct Worker; struct WorkerGlobal { - bool run_always; bool shutdown; + bool running; uint32_t max_request; + /** + * worker is shared memory, visible in other work processes. + * When a worker process restarts, it may be held by both the old and new processes simultaneously, + * necessitating careful handling of the state. + */ Worker *worker; + /** + * worker_copy is a copy of worker, + * but it must be local memory and only used within the current process or thread. + * It is not visible to other worker processes. + */ + Worker *worker_copy; time_t exit_time; }; @@ -115,6 +126,7 @@ struct Worker { WorkerId id; ProcessPool *pool; MsgQueue *queue; + bool shared; bool redirect_stdout; bool redirect_stdin; @@ -148,11 +160,33 @@ struct Worker { void *ptr2; ssize_t send_pipe_message(const void *buf, size_t n, int flags); + bool has_exceeded_max_request(); + void set_max_request(uint32_t max_request, uint32_t max_request_grace); + /** + * Init global state for worker process. + * Must be called after the process is spawned and before the main loop is executed. + */ + void init(); + void shutdown(); + bool is_shutdown(); + bool is_running(); void set_status(enum swWorkerStatus _status) { status = _status; } + void set_status_to_idle() { + set_status(SW_WORKER_IDLE); + } + + void set_status_to_busy() { + set_status(SW_WORKER_BUSY); + } + + void add_request_count() { + request_count++; + } + bool is_busy() { return status == SW_WORKER_BUSY; } @@ -285,7 +319,6 @@ struct ProcessPool { void set_protocol(enum ProtocolType _protocol_type); void set_max_request(uint32_t _max_request, uint32_t _max_request_grace); - int get_max_request(); bool detach(); int wait(); int start(); @@ -327,3 +360,7 @@ static sw_inline int swoole_kill(pid_t __pid, int __sig) { extern swoole::WorkerGlobal SwooleWG; // Worker Global Variable typedef swoole::ProtocolType swProtocolType; + +static inline swoole::Worker *sw_worker() { + return SwooleWG.worker; +} diff --git a/include/swoole_server.h b/include/swoole_server.h index 0ef0f43fff2..1a33f5a0ff6 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -795,10 +795,13 @@ class Server { EventData *task_result = nullptr; /** - * user process + * Used for process management, saving the mapping relationship between PID and worker pointers */ std::vector user_worker_list; std::unordered_map user_worker_map; + /** + * Shared memory, sharing state between processes + */ Worker *user_workers = nullptr; std::unordered_map commands; @@ -933,6 +936,8 @@ class Server { bool add_command(const std::string &command, int accepted_process_types, const Command::Handler &func); Connection *add_connection(ListenPort *ls, network::Socket *_socket, int server_fd); void abort_connection(Reactor *reactor, ListenPort *ls, network::Socket *_socket); + void abort_worker(Worker *worker); + void reset_worker_counter(Worker *worker); int connection_incoming(Reactor *reactor, Connection *conn); int get_idle_worker_num(); @@ -1085,6 +1090,10 @@ class Server { return factory != nullptr; } + bool is_running() { + return running; + } + bool is_master() { return SwooleG.process_type == SW_PROCESS_MASTER; } @@ -1093,6 +1102,10 @@ class Server { return SwooleG.process_type == SW_PROCESS_WORKER; } + bool is_event_worker() { + return is_worker(); + } + bool is_task_worker() { return SwooleG.process_type == SW_PROCESS_TASKWORKER; } @@ -1232,6 +1245,8 @@ class Server { void call_hook(enum HookType type, void *arg); void call_worker_start_callback(Worker *worker); + void call_worker_stop_callback(Worker *worker); + void call_worker_error_callback(Worker *worker, const ExitStatus &status); ResultCode call_command_handler(MessageBus &mb, uint16_t worker_id, network::Socket *sock); std::string call_command_handler_in_master(int command_id, const std::string &msg); void call_command_callback(int64_t request_id, const std::string &result); @@ -1353,6 +1368,7 @@ class Server { static void read_worker_message(ProcessPool *pool, EventData *msg); void drain_worker_pipe(); + void clean_worker_connections(Worker *worker); void check_worker_exit_status(Worker *worker, const ExitStatus &exit_status); diff --git a/include/swoole_socket.h b/include/swoole_socket.h index 1626d8d09d0..c1990adea0b 100644 --- a/include/swoole_socket.h +++ b/include/swoole_socket.h @@ -64,20 +64,9 @@ enum { }; namespace swoole { -namespace network { +struct GetaddrinfoRequest; -struct GetaddrinfoRequest { - const char *hostname; - const char *service; - int family; - int socktype; - int protocol; - int error; - void *result; - int count; - - void parse_result(std::vector &retval); -}; +namespace network { struct SendfileTask { off_t offset; diff --git a/include/swoole_static_handler.h b/include/swoole_static_handler.h index 71d2e8711ca..c35d7bf78dc 100644 --- a/include/swoole_static_handler.h +++ b/include/swoole_static_handler.h @@ -67,6 +67,15 @@ class StaticHandler { bool get_dir_files(); bool set_filename(const std::string &filename); + bool catch_error() { + if (last) { + status_code = SW_HTTP_NOT_FOUND; + return true; + } else { + return false; + } + } + bool has_index_file() { return !index_file.empty(); } @@ -116,6 +125,8 @@ class StaticHandler { return std::string(filename, l_filename); } + bool get_absolute_path(); + size_t get_filesize() { return file_stat.st_size; } @@ -128,6 +139,26 @@ class StaticHandler { return S_ISDIR(file_stat.st_mode); } + bool is_link() { + return S_ISLNK(file_stat.st_mode); + } + + bool is_file() { + return S_ISREG(file_stat.st_mode); + } + + bool is_absolute_path() { + return swoole_strnpos(filename, l_filename, SW_STRL("..")) == -1; + } + + bool is_located_in_document_root() { + const std::string &document_root = serv->get_document_root(); + const size_t l_document_root = document_root.length(); + + return l_filename > l_document_root && filename[l_document_root] == '/' && + swoole_str_starts_with(filename, l_filename, document_root.c_str(), l_document_root); + } + size_t get_content_length() { return content_length; } diff --git a/include/swoole_table.h b/include/swoole_table.h index e6762c0623f..d7b0af240dc 100644 --- a/include/swoole_table.h +++ b/include/swoole_table.h @@ -198,8 +198,6 @@ class Table { TableRow *get(const char *key, uint16_t keylen, TableRow **rowlock); bool del(const char *key, uint16_t keylen); void forward(); - // only release local memory of the current process - void free(); // release shared memory void destroy(); diff --git a/include/swoole_version.h b/include/swoole_version.h index 0d3f5dccd20..9b9a34d6525 100644 --- a/include/swoole_version.h +++ b/include/swoole_version.h @@ -20,10 +20,10 @@ #define SWOOLE_MAJOR_VERSION 5 #define SWOOLE_MINOR_VERSION 1 -#define SWOOLE_RELEASE_VERSION 4 +#define SWOOLE_RELEASE_VERSION 6 #define SWOOLE_EXTRA_VERSION "" -#define SWOOLE_VERSION "5.1.4" -#define SWOOLE_VERSION_ID 50104 +#define SWOOLE_VERSION "5.1.6" +#define SWOOLE_VERSION_ID 50106 #define SWOOLE_API_VERSION_ID 0x202208a #define SWOOLE_BUG_REPORT \ diff --git a/package.xml b/package.xml index ab07241349d..9c491f50901 100644 --- a/package.xml +++ b/package.xml @@ -51,10 +51,10 @@ doubaokun@php.net yes - 2024-08-22 - + 2024-11-27 + - 5.1.4 + 5.1.6 5.0 @@ -63,11 +63,13 @@ Apache2.0 - - Fix broken build with GCC 14. @remicollet - - Fix could not send SSL negotiation packet(Resource temporarily unavailable). @NathanFreeman - - Fix the issue where certain critical parameters of `Swoole\Server` are not reset to 0 during process restart. @NathanFreeman - - Fix the problem where `Swoole\Http\Request::getMethod()` returns the incorrect request method when `HTTP2` is enabled. @matyhtf - - Optimize `Swoole\Http\Response::end()`. Response data larger than 16K will be sent directly through the socket, while data smaller than or equal to 16K will be copied to the buffer first before being sent out via the socket. @NathanFreeman + - Fixed the issue where `Swoole\Http\Response::end()` returns `null`. @NathanFreeman + - Fixed the problem where the mutex lock of `Swoole\Table` could not be used before the process exits. @matyhtf + - Fixed the failure of `Swoole\Server::stop()` caused by using named parameters. @matyhtf + - Fixed the issue where the `runtime tcp` module did not support dynamically enabling SSL encryption. @matyhtf + - Fixed the `Fatal error` issue caused by the timeout feature of `PHP` in `ZTS` mode. @matyhtf + - Fixed the problem where `Swoole\Coroutine::getaddrinfo()` method could lead to SIGSEGV. @matyhtf + - Fixed the issue where the HTTP client running for a long time resulted in incorrect timeout settings. @matyhtf @@ -76,6 +78,7 @@ + @@ -1130,6 +1133,7 @@ + @@ -1494,6 +1498,8 @@ + + @@ -1511,8 +1517,11 @@ + + + @@ -1882,7 +1891,6 @@ - @@ -1983,10 +1991,12 @@ + + + + - - @@ -2118,6 +2128,7 @@ + @@ -2129,6 +2140,7 @@ + @@ -2567,15 +2579,16 @@ 8.0.0 + 8.3.99 - 1.4.0 + 1.10.0 swoole - + diff --git a/php_swoole.h b/php_swoole.h index aa6cb096f06..42e9ae3878e 100644 --- a/php_swoole.h +++ b/php_swoole.h @@ -17,6 +17,10 @@ #ifndef PHP_SWOOLE_H #define PHP_SWOOLE_H +#ifdef __cplusplus +extern "C" { +#endif + #include "php.h" #include "php_ini.h" #include "php_globals.h" @@ -37,6 +41,10 @@ #include "config.h" #endif +#ifdef __cplusplus +} +#endif + extern zend_module_entry swoole_module_entry; #define phpext_swoole_ptr &swoole_module_entry diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml index 74bc9234312..47d8451c35a 100755 --- a/scripts/docker-compose.yml +++ b/scripts/docker-compose.yml @@ -39,7 +39,7 @@ services: POSTGRES_DB: test POSTGRES_PASSWORD: root oracle: - image: gvenzl/oracle-xe:slim + image: gvenzl/oracle-free:slim container_name: "oracle" environment: ORACLE_PASSWORD: oracle diff --git a/scripts/route.sh b/scripts/route.sh index 07272ae87aa..ae82f2e48c3 100755 --- a/scripts/route.sh +++ b/scripts/route.sh @@ -6,7 +6,7 @@ export DOCKER_COMPOSE_VERSION="1.21.0" [ -z "${SWOOLE_BRANCH}" ] && export SWOOLE_BRANCH="master" [ -z "${SWOOLE_BUILD_DIR}" ] && export SWOOLE_BUILD_DIR=$(cd "$(dirname "$0")";cd ../;pwd) [ -z "${PHP_VERSION_ID}" ] && export PHP_VERSION_ID=`php -r "echo PHP_VERSION_ID;"` -if [ ${PHP_VERSION_ID} -lt 80300 ]; then +if [ ${PHP_VERSION_ID} -lt 80400 ]; then export PHP_VERSION="`php -r "echo PHP_MAJOR_VERSION;"`.`php -r "echo PHP_MINOR_VERSION;"`" else export PHP_VERSION="rc" diff --git a/src/core/base.cc b/src/core/base.cc index 37b723a6dc6..2b81a31e5d2 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -97,20 +97,12 @@ static ssize_t getrandom(void *buffer, size_t size, unsigned int __flags) { #endif swoole::Global SwooleG = {}; -__thread swoole::ThreadGlobal SwooleTG = {}; +thread_local swoole::ThreadGlobal SwooleTG = {}; +thread_local char sw_error[SW_ERROR_MSG_SIZE]; static std::unordered_map functions; static swoole::Logger *g_logger_instance = nullptr; -#ifdef __MACH__ -static __thread char _sw_error_buf[SW_ERROR_MSG_SIZE]; -char *sw_error_() { - return _sw_error_buf; -} -#else -__thread char sw_error[SW_ERROR_MSG_SIZE]; -#endif - static void swoole_fatal_error_impl(int code, const char *format, ...); swoole::Logger *sw_logger() { @@ -283,6 +275,12 @@ void swoole_clean(void) { delete SwooleTG.buffer_stack; SwooleTG.buffer_stack = nullptr; } + SW_LOOP_N(SW_MAX_HOOK_TYPE) { + if (SwooleG.hooks[i]) { + auto hooks = static_cast *>(SwooleG.hooks[i]); + delete hooks; + } + } swoole_signal_clear(); SwooleG = {}; } @@ -425,6 +423,10 @@ pid_t swoole_fork(int flags) { * reset signal handler */ swoole_signal_clear(); + + if (swoole_isset_hook(SW_GLOBAL_HOOK_AFTER_FORK)) { + swoole_call_hook(SW_GLOBAL_HOOK_AFTER_FORK, nullptr); + } } return pid; diff --git a/src/coroutine/socket.cc b/src/coroutine/socket.cc index a141d2b1ebe..7e4d21efb80 100644 --- a/src/coroutine/socket.cc +++ b/src/coroutine/socket.cc @@ -1220,6 +1220,11 @@ Socket *Socket::accept(double timeout) { if (sw_unlikely(!is_available(SW_EVENT_READ))) { return nullptr; } +#ifdef SW_USE_OPENSSL + if (ssl_is_enable() && sw_unlikely(ssl_context->context == nullptr) && !ssl_context_create()) { + return nullptr; + } +#endif network::Socket *conn = socket->accept(); if (conn == nullptr && errno == EAGAIN) { TimerController timer(&read_timer, timeout == 0 ? read_timeout : timeout, this, timer_callback); @@ -1245,10 +1250,7 @@ Socket *Socket::accept(double timeout) { } #ifdef SW_USE_OPENSSL -bool Socket::ssl_check_context() { - if (socket->ssl || (get_ssl_context() && get_ssl_context()->get_context())) { - return true; - } +bool Socket::ssl_context_create() { if (socket->is_dgram()) { #ifdef SW_SUPPORT_DTLS socket->dtls = 1; @@ -1261,7 +1263,6 @@ bool Socket::ssl_check_context() { } ssl_context->http_v2 = http2; if (!ssl_context->create()) { - swoole_warning("swSSL_get_context() error"); return false; } socket->ssl_send_ = 1; @@ -1295,12 +1296,20 @@ bool Socket::ssl_handshake() { if (sw_unlikely(!is_available(SW_EVENT_RDWR))) { return false; } - if (!ssl_check_context()) { + /** + * If the ssl_context is empty, it indicates that this socket was not a connection + * returned by a server socket accept, and a new ssl_context needs to be created. + */ + if (ssl_context->context == nullptr && !ssl_context_create()) { return false; } if (!ssl_create(get_ssl_context())) { return false; } + /** + * The server will use ssl_accept to complete the SSL handshake, + * while the client will use ssl_connect. + */ if (!ssl_is_server) { while (true) { if (socket->ssl_connect() < 0) { diff --git a/src/coroutine/system.cc b/src/coroutine/system.cc index 001d66592f3..087e8712ced 100644 --- a/src/coroutine/system.cc +++ b/src/coroutine/system.cc @@ -137,8 +137,8 @@ ssize_t System::write_file(const char *file, char *buf, size_t length, bool lock std::string gethostbyname_impl_with_async(const std::string &hostname, int domain, double timeout) { AsyncEvent ev{}; - GethostbynameRequest dns_request(hostname.c_str(), domain); - ev.data = &dns_request; + auto req = new GethostbynameRequest(hostname, domain); + ev.data = std::shared_ptr(req); ev.retval = 1; coroutine::async(async::handler_gethostbyname, ev, timeout); @@ -150,7 +150,7 @@ std::string gethostbyname_impl_with_async(const std::string &hostname, int domai swoole_set_last_error(ev.error); return ""; } else { - std::string addr(dns_request.addr); + std::string addr(req->addr); return addr; } } @@ -199,30 +199,20 @@ std::vector System::getaddrinfo( assert(family == AF_INET || family == AF_INET6); AsyncEvent ev{}; - network::GetaddrinfoRequest req{}; - - ev.data = &req; - - struct sockaddr_in6 result_buffer[SW_DNS_HOST_BUFFER_SIZE]; - - req.hostname = hostname.c_str(); - req.family = family; - req.socktype = socktype; - req.protocol = protocol; - req.service = service.empty() ? nullptr : service.c_str(); - req.result = result_buffer; + auto req = new GetaddrinfoRequest(hostname, family, socktype, protocol, service); + ev.data = std::shared_ptr(req); coroutine::async(async::handler_getaddrinfo, ev, timeout); std::vector retval; - if (ev.retval == -1 || req.error != 0) { + if (ev.retval == -1 || req->error != 0) { if (ev.error == SW_ERROR_AIO_TIMEOUT) { ev.error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT; } swoole_set_last_error(ev.error); } else { - req.parse_result(retval); + req->parse_result(retval); } return retval; diff --git a/src/memory/table.cc b/src/memory/table.cc index 76f80041a7c..c09dc3e8dc1 100644 --- a/src/memory/table.cc +++ b/src/memory/table.cc @@ -55,13 +55,6 @@ Table *Table::make(uint32_t rows_size, float conflict_proportion) { return table; } -void Table::free() { - delete mutex; - delete iterator; - delete column_map; - delete column_list; -} - bool Table::add_column(const std::string &_name, enum TableColumn::Type _type, size_t _size) { if (_type < TableColumn::TYPE_INT || _type > TableColumn::TYPE_STRING) { swoole_warning("unknown column type"); diff --git a/src/network/client.cc b/src/network/client.cc index 816265c9a7c..6706defa2ce 100644 --- a/src/network/client.cc +++ b/src/network/client.cc @@ -615,14 +615,13 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou if (cli->wait_dns) { AsyncEvent ev{}; - auto dns_request = new GethostbynameRequest(cli->server_host, cli->_sock_domain); - ev.data = dns_request; + auto req = new GethostbynameRequest(cli->server_host, cli->_sock_domain); + ev.data = std::shared_ptr(req);; ev.object = cli; ev.handler = async::handler_gethostbyname; ev.callback = Client_onResolveCompleted; if (swoole::async::dispatch(&ev) == nullptr) { - delete dns_request; return SW_ERR; } else { return SW_OK; @@ -1112,17 +1111,13 @@ static void Client_onTimeout(Timer *timer, TimerNode *tnode) { } static void Client_onResolveCompleted(AsyncEvent *event) { - auto dns_request = (GethostbynameRequest *) event->data; - if (event->canceled) { - delete dns_request; - return; - } + GethostbynameRequest *req = dynamic_cast(event->data.get()); Client *cli = (Client *) event->object; cli->wait_dns = 0; if (event->error == 0) { - Client_tcp_connect_async(cli, dns_request->addr, cli->server_port, cli->timeout, 1); + Client_tcp_connect_async(cli, req->addr, cli->server_port, cli->timeout, 1); } else { swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED); cli->socket->removed = 1; @@ -1131,7 +1126,6 @@ static void Client_onResolveCompleted(AsyncEvent *event) { cli->onError(cli); } } - delete dns_request; } static int Client_onWrite(Reactor *reactor, Event *event) { diff --git a/src/network/dns.cc b/src/network/dns.cc index b96172ca017..22ac3ab9dd8 100644 --- a/src/network/dns.cc +++ b/src/network/dns.cc @@ -344,7 +344,7 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam temp = &packet[steps]; j = 0; while (*temp != 0) { - if ((uchar)(*temp) == 0xc0) { + if ((uchar) (*temp) == 0xc0) { ++temp; temp = &packet[(uint8_t) *temp]; } else { @@ -373,7 +373,7 @@ std::vector dns_lookup_impl_with_socket(const char *domain, int fam temp = &packet[steps]; j = 0; while (*temp != 0) { - if ((uchar)(*temp) == 0xc0) { + if ((uchar) (*temp) == 0xc0) { ++temp; temp = &packet[(uint8_t) *temp]; } else { @@ -767,36 +767,40 @@ int getaddrinfo(GetaddrinfoRequest *req) { hints.ai_socktype = req->socktype; hints.ai_protocol = req->protocol; - int ret = ::getaddrinfo(req->hostname, req->service, &hints, &result); + int ret = ::getaddrinfo(req->hostname.c_str(), req->service.c_str(), &hints, &result); if (ret != 0) { req->error = ret; return SW_ERR; } - void *buffer = req->result; int i = 0; - for (ptr = result; ptr != nullptr; ptr = ptr->ai_next) { + for (ptr = result; ptr != nullptr; ptr = ptr->ai_next, i++) { + } + req->count = SW_MIN(i, SW_DNS_HOST_BUFFER_SIZE); + req->results.resize(req->count); + + for (ptr = result, i = 0; ptr != nullptr; ptr = ptr->ai_next, i++) { switch (ptr->ai_family) { case AF_INET: - memcpy((char *) buffer + (i * sizeof(struct sockaddr_in)), ptr->ai_addr, sizeof(struct sockaddr_in)); + memcpy(&req->results[i], ptr->ai_addr, sizeof(struct sockaddr_in)); break; case AF_INET6: - memcpy((char *) buffer + (i * sizeof(struct sockaddr_in6)), ptr->ai_addr, sizeof(struct sockaddr_in6)); + memcpy(&req->results[i], ptr->ai_addr, sizeof(struct sockaddr_in6)); break; default: swoole_warning("unknown socket family[%d]", ptr->ai_family); break; } - i++; if (i == SW_DNS_HOST_BUFFER_SIZE) { break; } } ::freeaddrinfo(result); req->error = 0; - req->count = i; + return SW_OK; } +} // namespace network void GetaddrinfoRequest::parse_result(std::vector &retval) { struct sockaddr_in *addr_v4; @@ -805,12 +809,12 @@ void GetaddrinfoRequest::parse_result(std::vector &retval) { char tmp[INET6_ADDRSTRLEN]; const char *r; - for (int i = 0; i < count; i++) { + for (auto &addr : results) { if (family == AF_INET) { - addr_v4 = (struct sockaddr_in *) ((char *) result + (i * sizeof(struct sockaddr_in))); + addr_v4 = (struct sockaddr_in *) &addr; r = inet_ntop(AF_INET, (const void *) &addr_v4->sin_addr, tmp, sizeof(tmp)); } else { - addr_v6 = (struct sockaddr_in6 *) ((char *) result + (i * sizeof(struct sockaddr_in6))); + addr_v6 = (struct sockaddr_in6 *) &addr; r = inet_ntop(AF_INET6, (const void *) &addr_v6->sin6_addr, tmp, sizeof(tmp)); } if (r) { @@ -818,5 +822,4 @@ void GetaddrinfoRequest::parse_result(std::vector &retval) { } } } -} // namespace network } // namespace swoole diff --git a/src/os/base.cc b/src/os/base.cc index 9d6c2d10576..5b30d56d141 100644 --- a/src/os/base.cc +++ b/src/os/base.cc @@ -85,14 +85,14 @@ namespace async { void handler_gethostbyname(AsyncEvent *event) { char addr[INET6_ADDRSTRLEN]; - auto request = (GethostbynameRequest *) event->data; - int ret = network::gethostbyname(request->family, request->name, addr); - sw_memset_zero(request->addr, request->addr_len); + auto req = dynamic_cast(event->data.get()); + int ret = network::gethostbyname(req->family, req->name.c_str(), addr); + sw_memset_zero(req->addr, req->addr_len); if (ret < 0) { event->error = SW_ERROR_DNSLOOKUP_RESOLVE_FAILED; } else { - if (inet_ntop(request->family, addr, request->addr, request->addr_len) == nullptr) { + if (inet_ntop(req->family, addr, req->addr, req->addr_len) == nullptr) { ret = -1; event->error = SW_ERROR_BAD_IPV6_ADDRESS; } else { @@ -104,7 +104,7 @@ void handler_gethostbyname(AsyncEvent *event) { } void handler_getaddrinfo(AsyncEvent *event) { - network::GetaddrinfoRequest *req = (network::GetaddrinfoRequest *) event->data; + auto req = dynamic_cast(event->data.get()); event->retval = network::getaddrinfo(req); event->error = req->error; } diff --git a/src/os/process_pool.cc b/src/os/process_pool.cc index 8c6212ea0ae..e3a4c4d1a69 100644 --- a/src/os/process_pool.cc +++ b/src/os/process_pool.cc @@ -457,6 +457,7 @@ pid_t ProcessPool::spawn(Worker *worker) { switch (pid) { // child case 0: + worker->init(); worker->pid = SwooleG.pid; SwooleG.process_id = worker->id; SwooleG.process_type = SW_PROCESS_WORKER; @@ -494,19 +495,6 @@ pid_t ProcessPool::spawn(Worker *worker) { return pid; } -int ProcessPool::get_max_request() { - int task_n; - if (max_request < 1) { - return -1; - } else { - task_n = max_request; - if (max_request_grace > 0) { - task_n += swoole_system_random(1, max_request_grace); - } - } - return task_n; -} - void ProcessPool::set_max_request(uint32_t _max_request, uint32_t _max_request_grace) { max_request = _max_request; max_request_grace = _max_request_grace; @@ -518,12 +506,7 @@ static int ProcessPool_worker_loop_with_task_protocol(ProcessPool *pool, Worker EventData buf; } out{}; - ssize_t n = 0, ret, worker_task_always = 0; - int task_n = pool->get_max_request(); - if (task_n <= 0) { - worker_task_always = 1; - task_n = 1; - } + ssize_t n = 0, ret; /** * Use from_fd save the task_worker->id @@ -536,7 +519,7 @@ static int ProcessPool_worker_loop_with_task_protocol(ProcessPool *pool, Worker out.mtype = worker->id + 1; } - while (pool->running && !SwooleWG.shutdown && task_n > 0) { + while (pool->running && !worker->is_shutdown() && !worker->has_exceeded_max_request()) { /** * fetch task */ @@ -609,8 +592,8 @@ static int ProcessPool_worker_loop_with_task_protocol(ProcessPool *pool, Worker goto _alarm_handler; } - if (ret >= 0 && !worker_task_always) { - task_n--; + if (ret >= 0) { + worker->add_request_count(); } } return SW_OK; @@ -986,4 +969,35 @@ void ProcessPool::destroy() { sw_mem_pool()->free(workers); } +void Worker::init() { + start_time = ::time(nullptr); + request_count = 0; + set_status_to_idle(); + SwooleWG.running = true; + SwooleWG.shutdown = false; +} + +void Worker::set_max_request(uint32_t max_request, uint32_t max_request_grace) { + if (max_request > 0 && max_request_grace > 0) { + max_request += swoole_system_random(1, max_request_grace); + } + SwooleWG.max_request = max_request; +} + +bool Worker::has_exceeded_max_request() { + return SwooleWG.max_request > 0 && request_count >= SwooleWG.max_request; +} + +void Worker::shutdown() { + status = SW_WORKER_EXIT; + SwooleWG.shutdown = true; +} + +bool Worker::is_shutdown() { + return SwooleWG.shutdown; +} + +bool Worker::is_running() { + return SwooleWG.running; +} } // namespace swoole diff --git a/src/reactor/base.cc b/src/reactor/base.cc index 0f593062015..bc3c1bc658e 100644 --- a/src/reactor/base.cc +++ b/src/reactor/base.cc @@ -48,7 +48,7 @@ ReactorImpl *make_reactor_kqueue(Reactor *_reactor, int max_events); ReactorImpl *make_reactor_select(Reactor *_reactor); -void ReactorImpl::after_removal_failure(network::Socket *_socket) { +void ReactorImpl::after_removal_failure(Socket *_socket) { if (!_socket->silent_remove) { swoole_sys_warning("failed to delete events[fd=%d#%d, type=%d, events=%d]", _socket->fd, @@ -297,7 +297,7 @@ ssize_t Reactor::_write(Reactor *reactor, Socket *socket, const void *buf, size_ return write_func(reactor, socket, n, send_fn, append_fn); } -ssize_t Reactor::_writev(Reactor *reactor, network::Socket *socket, const iovec *iov, size_t iovcnt) { +ssize_t Reactor::_writev(Reactor *reactor, Socket *socket, const iovec *iov, size_t iovcnt) { #ifdef SW_USE_OPENSSL if (socket->ssl) { swoole_error_log(SW_LOG_WARNING, SW_ERROR_OPERATION_NOT_SUPPORT, "does not support SSL"); @@ -359,13 +359,13 @@ int Reactor::_writable_callback(Reactor *reactor, Event *ev) { return SW_OK; } -void Reactor::drain_write_buffer(swSocket *socket) { +void Reactor::drain_write_buffer(Socket *socket) { Event event = {}; event.socket = socket; event.fd = socket->fd; while (!Buffer::empty(socket->out_buffer)) { - if (socket->wait_event(network::Socket::default_write_timeout, SW_EVENT_WRITE) == SW_ERR) { + if (socket->wait_event(Socket::default_write_timeout, SW_EVENT_WRITE) == SW_ERR) { break; } _writable_callback(this, &event); diff --git a/src/server/base.cc b/src/server/base.cc index bdb5ef37e47..eb4349e01d9 100644 --- a/src/server/base.cc +++ b/src/server/base.cc @@ -19,7 +19,6 @@ namespace swoole { bool BaseFactory::start() { - SwooleWG.run_always = true; return true; } diff --git a/src/server/manager.cc b/src/server/manager.cc index efe33394a68..cd2ad745394 100644 --- a/src/server/manager.cc +++ b/src/server/manager.cc @@ -169,6 +169,14 @@ void Server::check_worker_exit_status(Worker *worker, const ExitStatus &exit_sta if (onWorkerError != nullptr) { onWorkerError(this, worker, exit_status); } + /** + * The work process has exited unexpectedly, requiring a cleanup of the shared memory state. + * This must be done between the termination of the old process and the initiation of the new one; + * otherwise, data contention may occur. + */ + if (worker->type == SW_PROCESS_WORKER) { + abort_worker(worker); + } } } @@ -608,19 +616,7 @@ pid_t Server::spawn_event_worker(Worker *worker) { return pid; } - // see https://github.com/swoole/swoole-src/issues/5407 - if (worker->concurrency > 0 && worker_num > 1) { - sw_atomic_sub_fetch(&gs->concurrency, worker->concurrency); - worker->concurrency = 0; - } - - // see https://github.com/swoole/swoole-src/issues/5432 - worker->request_count = 0; - worker->response_count = 0; - worker->dispatch_count = 0; - if (is_base_mode()) { - gs->connection_nums[worker->id] = 0; gs->event_workers.main_loop(&gs->event_workers, worker); } else { start_event_worker(worker); @@ -670,7 +666,7 @@ bool Server::reload(bool reload_all_workers) { } if (getpid() != gs->manager_pid) { - return swoole_kill(get_manager_pid(), reload_all_workers ? SIGUSR1 : SIGUSR2) != 0; + return swoole_kill(get_manager_pid(), reload_all_workers ? SIGUSR1 : SIGUSR2) == 0; } ProcessPool *pool = &gs->event_workers; diff --git a/src/server/master.cc b/src/server/master.cc index 69f09e498a9..ba2017bbd50 100644 --- a/src/server/master.cc +++ b/src/server/master.cc @@ -575,33 +575,8 @@ void Server::init_worker(Worker *worker) { } #endif - if (max_request < 1) { - SwooleWG.run_always = true; - } else { - SwooleWG.max_request = max_request; - if (max_request_grace > 0) { - SwooleWG.max_request += swoole_system_random(1, max_request_grace); - } - } - - worker->start_time = ::time(nullptr); - worker->request_count = 0; -} - -void Server::call_worker_start_callback(Worker *worker) { - void *hook_args[2]; - hook_args[0] = this; - hook_args[1] = (void *) (uintptr_t) worker->id; - - if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_WORKER_START)) { - swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_WORKER_START, hook_args); - } - if (isset_hook(HOOK_WORKER_START)) { - call_hook(Server::HOOK_WORKER_START, hook_args); - } - if (onWorkerStart) { - onWorkerStart(this, worker); - } + worker->init(); + worker->set_max_request(max_request, max_request_grace); } int Server::start() { @@ -1895,6 +1870,34 @@ void Server::abort_connection(Reactor *reactor, ListenPort *ls, Socket *_socket) } } +// see https://github.com/swoole/swoole-src/issues/5407 +// see https://github.com/swoole/swoole-src/issues/5432 +void Server::reset_worker_counter(Worker *worker) { + auto value = worker->concurrency; + if (value > 0 && sw_atomic_value_cmp_set(&worker->concurrency, value, 0) == value) { + sw_atomic_sub_fetch(&gs->concurrency, value); + if ((int) gs->concurrency < 0) { + gs->concurrency = 0; + } + } + worker->request_count = 0; + worker->response_count = 0; + worker->dispatch_count = 0; +} + +void Server::abort_worker(Worker *worker) { + reset_worker_counter(worker); + + if (is_base_mode()) { + SW_LOOP_N(SW_SESSION_LIST_SIZE) { + Session *session = get_session(i); + if (session->reactor_id == worker->id) { + session->fd = 0; + } + } + } +} + /** * new connection */ diff --git a/src/server/reactor_process.cc b/src/server/reactor_process.cc index 446e03f032f..cb6703775b7 100644 --- a/src/server/reactor_process.cc +++ b/src/server/reactor_process.cc @@ -185,10 +185,6 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { SwooleG.pid = getpid(); SwooleG.process_id = worker->id; - if (serv->max_request > 0) { - SwooleWG.run_always = false; - } - SwooleWG.max_request = serv->max_request; SwooleWG.worker = worker; SwooleTG.id = 0; @@ -208,6 +204,8 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { Server::worker_signal_init(); + serv->gs->connection_nums[worker->id] = 0; + for (auto ls : serv->ports) { #ifdef HAVE_REUSEPORT if (ls->is_stream() && serv->enable_reuse_port) { @@ -217,6 +215,7 @@ static int ReactorProcess_loop(ProcessPool *pool, Worker *worker) { } } #endif + ls->gs->connection_nums[worker->id] = 0; if (reactor->add(ls->socket, SW_EVENT_READ) < 0) { return SW_ERR; } diff --git a/src/server/static_handler.cc b/src/server/static_handler.cc index 50bce294e30..e0015bfad23 100644 --- a/src/server/static_handler.cc +++ b/src/server/static_handler.cc @@ -45,7 +45,7 @@ bool StaticHandler::is_modified(const std::string &date_if_modified_since) { } else if (strptime(date_tmp, SW_HTTP_ASCTIME_DATE, &tm3) != nullptr) { date_format = SW_HTTP_ASCTIME_DATE; } - return date_format && mktime(&tm3) - (int) serv->timezone_ >= get_file_mtime(); + return date_format && mktime(&tm3) - (time_t) serv->timezone_ >= get_file_mtime(); } bool StaticHandler::is_modified_range(const std::string &date_range) { @@ -87,6 +87,16 @@ std::string StaticHandler::get_date_last_modified() { return std::string(date_last_modified); } +bool StaticHandler::get_absolute_path() { + char abs_path[PATH_MAX]; + if (!realpath(filename, abs_path)) { + return false; + } + strncpy(filename, abs_path, sizeof(abs_path)); + l_filename = strlen(filename); + return true; +} + bool StaticHandler::hit() { char *p = filename; const char *url = request_url.c_str(); @@ -102,9 +112,10 @@ bool StaticHandler::hit() { size_t n = params ? params - url : url_length; const std::string &document_root = serv->get_document_root(); + const size_t l_document_root = document_root.length(); - memcpy(p, document_root.c_str(), document_root.length()); - p += document_root.length(); + memcpy(p, document_root.c_str(), l_document_root); + p += l_document_root; if (serv->locations->size() > 0) { for (auto i = serv->locations->begin(); i != serv->locations->end(); i++) { @@ -117,8 +128,8 @@ bool StaticHandler::hit() { } } - if (document_root.length() + n >= PATH_MAX) { - return false; + if (l_document_root + n >= PATH_MAX) { + return catch_error(); } memcpy(p, url, n); @@ -132,50 +143,27 @@ bool StaticHandler::hit() { l_filename = http_server::url_decode(filename, p - filename); filename[l_filename] = '\0'; - if (swoole_strnpos(url, n, SW_STRL("..")) == -1) { - goto _detect_mime_type; - } - - char real_path[PATH_MAX]; - if (!realpath(filename, real_path)) { - if (last) { - status_code = SW_HTTP_NOT_FOUND; - return true; - } else { - return false; - } - } - - if (real_path[document_root.length()] != '/') { - return false; - } - - if (swoole_streq(real_path, strlen(real_path), document_root.c_str(), document_root.length()) != 0) { - return false; - } - -// non-static file -_detect_mime_type: -// file does not exist -check_stat: + // The file does not exist if (lstat(filename, &file_stat) < 0) { - if (last) { - status_code = SW_HTTP_NOT_FOUND; - return true; - } else { - return false; - } + return catch_error(); } - if (S_ISLNK(file_stat.st_mode)) { - char buf[PATH_MAX]; - ssize_t byte = ::readlink(filename, buf, sizeof(buf) - 1); - if (byte <= 0) { - return false; + // The filename is relative path, allows for the resolution of symbolic links. + // This path is formed by concatenating the document root and that is permitted for access. + if (is_absolute_path()) { + if (is_link()) { + // Use the realpath function to resolve a symbolic link to its actual path. + if (!get_absolute_path()) { + return catch_error(); + } + if (lstat(filename, &file_stat) < 0) { + return catch_error(); + } + } + } else { + if (!get_absolute_path() || !is_located_in_document_root()) { + return catch_error(); } - buf[byte] = 0; - swoole_strlcpy(filename, buf, sizeof(filename)); - goto check_stat; } if (serv->http_index_files && !serv->http_index_files->empty() && is_dir()) { @@ -186,11 +174,11 @@ bool StaticHandler::hit() { return true; } - if (!swoole::mime_type::exists(filename) && !last) { + if (!mime_type::exists(filename) && !last) { return false; } - if (!S_ISREG(file_stat.st_mode)) { + if (!is_file()) { return false; } @@ -271,23 +259,23 @@ bool StaticHandler::get_dir_files() { return true; } -bool StaticHandler::set_filename(const std::string &filename) { - char *p = this->filename + l_filename; +bool StaticHandler::set_filename(const std::string &_filename) { + char *p = filename + l_filename; if (*p != '/') { *p = '/'; p += 1; } - memcpy(p, filename.c_str(), filename.length()); - p += filename.length(); + memcpy(p, _filename.c_str(), _filename.length()); + p += _filename.length(); *p = 0; - if (lstat(this->filename, &file_stat) < 0) { + if (lstat(filename, &file_stat) < 0) { return false; } - if (!S_ISREG(file_stat.st_mode)) { + if (!is_file()) { return false; } @@ -327,7 +315,7 @@ void StaticHandler::parse_range(const char *range, const char *if_range) { } while (*p >= '0' && *p <= '9') { - if (start >= cutoff && (start > cutoff || (size_t)(*p - '0') > cutlim)) { + if (start >= cutoff && (start > cutoff || (size_t) (*p - '0') > cutlim)) { status_code = SW_HTTP_RANGE_NOT_SATISFIABLE; return; } @@ -364,7 +352,7 @@ void StaticHandler::parse_range(const char *range, const char *if_range) { } while (*p >= '0' && *p <= '9') { - if (end >= cutoff && (end > cutoff || (size_t)(*p - '0') > cutlim)) { + if (end >= cutoff && (end > cutoff || (size_t) (*p - '0') > cutlim)) { status_code = SW_HTTP_RANGE_NOT_SATISFIABLE; return; } diff --git a/src/server/task_worker.cc b/src/server/task_worker.cc index 6923e3a832f..1f55d5dd7d2 100644 --- a/src/server/task_worker.cc +++ b/src/server/task_worker.cc @@ -191,19 +191,9 @@ static void TaskWorker_onStart(ProcessPool *pool, Worker *worker) { TaskWorker_signal_init(pool); serv->worker_start_callback(worker); - worker->start_time = ::time(nullptr); - worker->request_count = 0; + worker->init(); + worker->set_max_request(pool->max_request, pool->max_request_grace); SwooleWG.worker = worker; - SwooleWG.worker->status = SW_WORKER_IDLE; - /** - * task_max_request - */ - if (pool->max_request > 0) { - SwooleWG.run_always = false; - SwooleWG.max_request = pool->get_max_request(); - } else { - SwooleWG.run_always = true; - } } static void TaskWorker_onStop(ProcessPool *pool, Worker *worker) { @@ -227,7 +217,7 @@ static int TaskWorker_onPipeReceive(Reactor *reactor, Event *event) { worker->status = SW_WORKER_IDLE; worker->request_count++; // maximum number of requests, process will exit. - if (!SwooleWG.run_always && worker->request_count >= SwooleWG.max_request) { + if (worker->has_exceeded_max_request()) { serv->stop_async_worker(worker); } return retval; diff --git a/src/server/worker.cc b/src/server/worker.cc index f75cb1c6b25..5b8aba04f3e 100644 --- a/src/server/worker.cc +++ b/src/server/worker.cc @@ -47,18 +47,17 @@ void Server::worker_signal_init(void) { } void Server::worker_signal_handler(int signo) { - if (!SwooleG.running || !sw_server()) { + if (!SwooleG.running || !sw_server() || !sw_worker() || !sw_server()->is_running()) { return; } switch (signo) { case SIGTERM: - // Event worker if (swoole_event_is_available()) { - sw_server()->stop_async_worker(SwooleWG.worker); - } - // Task worker - else { - SwooleWG.shutdown = true; + // Event Worker + sw_server()->stop_async_worker(sw_worker()); + } else { + // Task Worker + sw_worker()->shutdown(); } break; // for test @@ -209,7 +208,7 @@ void Server::worker_accept_event(DataHead *info) { worker->status = SW_WORKER_IDLE; // maximum number of requests, process will exit. - if (!SwooleWG.run_always && worker->request_count >= SwooleWG.max_request) { + if (worker->has_exceeded_max_request()) { stop_async_worker(worker); } } @@ -261,7 +260,7 @@ void Server::worker_start_callback(Worker *worker) { } SW_LOOP_N(worker_num + task_worker_num) { - if (SwooleG.process_id == i) { + if (worker->id == i) { continue; } Worker *other_worker = get_worker(i); @@ -285,31 +284,66 @@ void Server::worker_start_callback(Worker *worker) { } void Server::worker_stop_callback(Worker *worker) { + call_worker_stop_callback(worker); +} + +void Server::call_worker_start_callback(Worker *worker) { + void *hook_args[2]; + hook_args[0] = this; + hook_args[1] = (void *) (uintptr_t) worker->id; + + if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_WORKER_START)) { + swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_WORKER_START, hook_args); + } + if (isset_hook(HOOK_WORKER_START)) { + call_hook(Server::HOOK_WORKER_START, hook_args); + } + + SwooleWG.running = true; + if (onWorkerStart) { + onWorkerStart(this, worker); + } +} + +void Server::call_worker_stop_callback(Worker *worker) { void *hook_args[2]; hook_args[0] = this; - hook_args[1] = (void *) (uintptr_t) SwooleG.process_id; + hook_args[1] = (void *) (uintptr_t) worker->id; + if (swoole_isset_hook(SW_GLOBAL_HOOK_BEFORE_WORKER_STOP)) { swoole_call_hook(SW_GLOBAL_HOOK_BEFORE_WORKER_STOP, hook_args); } if (onWorkerStop) { onWorkerStop(this, worker); } + if (!message_bus.empty()) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_UNPROCESSED_DATA, "unprocessed data in the worker process buffer"); message_bus.clear(); } + + SwooleWG.running = false; + if (SwooleWG.worker_copy) { + delete SwooleWG.worker_copy; + SwooleWG.worker_copy = nullptr; + SwooleWG.worker = nullptr; + } } void Server::stop_async_worker(Worker *worker) { worker->status = SW_WORKER_EXIT; Reactor *reactor = SwooleTG.reactor; + worker->shutdown(); + if (worker->type == SW_PROCESS_WORKER) { + reset_worker_counter(worker); + } + /** * force to end. */ if (reload_async == 0) { - running = false; reactor->running = false; return; } @@ -320,8 +354,8 @@ void Server::stop_async_worker(Worker *worker) { } // Separated from the event worker process pool - worker = (Worker *) sw_malloc(sizeof(*worker)); - *worker = *SwooleWG.worker; + SwooleWG.worker_copy = new Worker{}; + *SwooleWG.worker_copy = *worker; SwooleWG.worker = worker; if (worker->pipe_worker && !worker->pipe_worker->removed) { @@ -354,10 +388,10 @@ void Server::stop_async_worker(Worker *worker) { } else { WorkerStopMessage msg; msg.pid = SwooleG.pid; - msg.worker_id = SwooleG.process_id; + msg.worker_id = worker->id; if (gs->event_workers.push_message(SW_WORKER_MESSAGE_STOP, &msg, sizeof(msg)) < 0) { - running = 0; + swoole_sys_warning("failed to push WORKER_STOP message"); } } @@ -366,9 +400,6 @@ void Server::stop_async_worker(Worker *worker) { SwooleWG.exit_time = ::time(nullptr); Worker_reactor_try_to_exit(reactor); - if (!reactor->running) { - running = false; - } } static void Worker_reactor_try_to_exit(Reactor *reactor) { @@ -384,10 +415,9 @@ static void Worker_reactor_try_to_exit(Reactor *reactor) { while (1) { if (reactor->if_exit()) { reactor->running = false; - break; } else { if (serv->onWorkerExit && call_worker_exit_func == 0) { - serv->onWorkerExit(serv, SwooleWG.worker); + serv->onWorkerExit(serv, sw_worker()); call_worker_exit_func = 1; continue; } @@ -396,7 +426,6 @@ static void Worker_reactor_try_to_exit(Reactor *reactor) { swoole_error_log( SW_LOG_WARNING, SW_ERROR_SERVER_WORKER_EXIT_TIMEOUT, "worker exit timeout, forced termination"); reactor->running = false; - break; } else { int timeout_msec = remaining_time * 1000; if (reactor->timeout_msec < 0 || reactor->timeout_msec > timeout_msec) { @@ -422,6 +451,16 @@ void Server::drain_worker_pipe() { } } +void Server::clean_worker_connections(Worker *worker) { + sw_reactor()->destroyed = true; + + if (is_base_mode()) { + foreach_connection([this](Connection *conn) { close(conn->session_id, true); }); + } else { + return; + } +} + /** * main loop [Worker] */ diff --git a/tests/include/api/curl_multi.php b/tests/include/api/curl_multi.php index f146e9fa018..30d457e8d8c 100644 --- a/tests/include/api/curl_multi.php +++ b/tests/include/api/curl_multi.php @@ -8,17 +8,14 @@ function swoole_test_curl_multi($options = []) { function swoole_test_curl_multi_ex($mh, $options = []) { $ch1 = curl_init(); $ch2 = curl_init(); - $userAgent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:129.0) Gecko/20100101 Firefox/129.0'; // 设置URL和相应的选项 curl_setopt($ch1, CURLOPT_URL, "https://www.baidu.com/"); curl_setopt($ch1, CURLOPT_HEADER, 0); - curl_setopt($ch2, CURLOPT_USERAGENT, $userAgent); curl_setopt($ch1, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch2, CURLOPT_URL, "https://www.zhihu.com/"); + curl_setopt($ch2, CURLOPT_URL, "https://www.gov.cn/"); curl_setopt($ch2, CURLOPT_HEADER, 0); - curl_setopt($ch2, CURLOPT_USERAGENT, $userAgent); curl_setopt($ch2, CURLOPT_RETURNTRANSFER, 1); $mh = curl_multi_init(); @@ -64,7 +61,7 @@ function swoole_test_curl_multi_ex($mh, $options = []) { Assert::eq($info3, false); Assert::contains(curl_multi_getcontent($ch1), 'baidu.com'); - Assert::contains(curl_multi_getcontent($ch2), 'zhihu'); + Assert::contains(curl_multi_getcontent($ch2), '中国政府网'); curl_multi_remove_handle($mh, $ch1); curl_multi_remove_handle($mh, $ch2); diff --git a/tests/include/config.php b/tests/include/config.php index e0e27f51bb7..0abbed2563e 100644 --- a/tests/include/config.php +++ b/tests/include/config.php @@ -78,7 +78,7 @@ /** ============== Oracle ============== */ define('ORACLE_PORT', '1521'); -define('ORACLE_SERVICE_NAME', 'xe'); +define('ORACLE_SERVICE_NAME', 'freepdb1'); define('ORACLE_USER', 'system'); define('ORACLE_PASSWORD', 'oracle'); if (IS_IN_CI) { diff --git a/tests/include/functions.php b/tests/include/functions.php index 4dd94504cad..d86b5e97ff5 100644 --- a/tests/include/functions.php +++ b/tests/include/functions.php @@ -852,3 +852,11 @@ function build_ftp_url(string $path = ''): string { return 'ftp://' . FTP_USER . ':' . FTP_PASS . '@' . FTP_HOST . ':' . FTP_PORT . '/' . $path; } + +function mkdir_if_not_exists(string $string): void +{ + if (!is_dir($string)) { + mkdir($string, 0777, true); + } +} + diff --git a/tests/include/skipif.inc b/tests/include/skipif.inc index faf324acd13..1f731049d36 100644 --- a/tests/include/skipif.inc +++ b/tests/include/skipif.inc @@ -45,7 +45,7 @@ function swoole_color(string $content, int $color): string function skip(string $reason, bool $is_skip = true, int $color = SWOOLE_COLOR_YELLOW) { if ($is_skip) { - exit('skip ' . swoole_color($reason, $color)); + exit('skip ' . swoole_color($reason, $color) . "\n"); } } diff --git a/tests/swoole_coroutine_system/getaddrinfo.phpt b/tests/swoole_coroutine_system/getaddrinfo.phpt index 5fda59a59b8..87e91851607 100644 --- a/tests/swoole_coroutine_system/getaddrinfo.phpt +++ b/tests/swoole_coroutine_system/getaddrinfo.phpt @@ -7,7 +7,7 @@ skip_if_offline(); --FILE-- +--FILE-- + +--EXPECT-- +DONE diff --git a/tests/swoole_event/add_after_server_start.phpt b/tests/swoole_event/add_after_server_start.phpt index 82263e3b5de..9fe59067db6 100644 --- a/tests/swoole_event/add_after_server_start.phpt +++ b/tests/swoole_event/add_after_server_start.phpt @@ -10,7 +10,7 @@ require __DIR__ . '/../include/bootstrap.php'; use Swoole\Server; -const FILE = __DIR__.'/tmp_result.txt'; +const FILE = __DIR__ . '/tmp_result.txt'; $pm = new SwooleTest\ProcessManager; $pm->parentFunc = function ($pid) use ($pm) { @@ -22,12 +22,12 @@ $pm->parentFunc = function ($pid) use ($pm) { $pm->childFunc = function () use ($pm) { $serv = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); $serv->set(array( - "worker_num" => 1, + 'worker_num' => 1, 'log_file' => '/dev/null', )); $serv->on("start", function (Server $serv) use ($pm) { - $fp = stream_socket_client("tcp://www.qq.com:80", $errno, $errstr, 30); - fwrite($fp, "GET / HTTP/1.1\r\nHost: www.qq.com\r\n\r\n"); + $fp = stream_socket_client("tcp://" . TEST_DOMAIN_2 . ":80", $errno, $errstr, 30); + fwrite($fp, "GET / HTTP/1.1\r\nHost: " . TEST_DOMAIN_2 . "\r\n\r\n"); Swoole\Event::add($fp, function ($fp) use ($pm) { $resp = fread($fp, 8192); diff --git a/tests/swoole_http2_client_coro/connect_twice.phpt b/tests/swoole_http2_client_coro/connect_twice.phpt index 798ca5f724b..88ff09e8a2f 100644 --- a/tests/swoole_http2_client_coro/connect_twice.phpt +++ b/tests/swoole_http2_client_coro/connect_twice.phpt @@ -6,29 +6,33 @@ swoole_http2_client_coro: connect twice connect(); - $req = new \Swoole\Http2\Request(); + $req = new Request(); + $uuid = uniqid(); $req->method = 'GET'; - $req->path = '/io?io=' . str_repeat('xxx', 1000); + $req->path = '/base64/' . base64_encode($uuid); $client->send($req); $chan->push(true); $resp = $client->recv(); Assert::eq($resp->statusCode, 200); - Assert::contains($resp->data, '知乎'); + Assert::eq($resp->data, $uuid); $chan->pop(); }); go(function () use ($client, $chan) { Assert::eq($client->connect(), false); - $req = new \Swoole\Http2\Request(); + $uuid = uniqid(); + $req = new Request(); $req->method = 'GET'; - $req->path = '/io?io=xxx'; + $req->path = '/base64/' . base64_encode($uuid); $client->send($req); $chan->push(true); Assert::eq($client->recv(), false); diff --git a/tests/swoole_http_client_coro/disable_keep_alive.phpt b/tests/swoole_http_client_coro/disable_keep_alive.phpt index 2db9b29d81c..6a809d9b98f 100644 --- a/tests/swoole_http_client_coro/disable_keep_alive.phpt +++ b/tests/swoole_http_client_coro/disable_keep_alive.phpt @@ -8,7 +8,7 @@ skip_if_offline(); set([ 'timeout' => 10, @@ -18,14 +18,14 @@ Co\run(function () { $cli->get('/'); Assert::same($cli->statusCode, 200); - Assert::true($cli->get('/contract.shtml')); + Assert::true($cli->get('/ch/tech/')); Assert::same($cli->statusCode, 200); // failed clear $cli->set([ 'timeout' => 0.001 ]); - Assert::false($cli->get('/contract.shtml')); + Assert::false($cli->get('/ch/tech/')); Assert::assert(empty($cli->headers)); Assert::assert(empty($cli->body)); }); diff --git a/tests/swoole_http_client_coro/http_proxy.phpt b/tests/swoole_http_client_coro/http_proxy.phpt index 21158bd5fc3..af8d9c39619 100644 --- a/tests/swoole_http_client_coro/http_proxy.phpt +++ b/tests/swoole_http_client_coro/http_proxy.phpt @@ -10,7 +10,7 @@ skip_if_offline(); setHeaders(['Host' => $domain]); // without host header it can also work well $cli->set([ @@ -20,7 +20,7 @@ go(function () { ]); $result = $cli->get('/'); Assert::assert($result); - Assert::assert(stripos($cli->body, 'tencent') !== false); + Assert::assert(stripos($cli->body, '百度') !== false); echo "DONE\n"; }); ?> diff --git a/tests/swoole_http_client_coro/multi_and_reuse.phpt b/tests/swoole_http_client_coro/multi_and_reuse.phpt index 16bdabbc244..31f2afbd97e 100644 --- a/tests/swoole_http_client_coro/multi_and_reuse.phpt +++ b/tests/swoole_http_client_coro/multi_and_reuse.phpt @@ -24,7 +24,7 @@ go(function () { } $baidu = createDeferCli('www.baidu.com', true); - $qq = createDeferCli('www.qq.com', true); + $qq = createDeferCli('news.qq.com', true); //first $baidu->get('/'); @@ -38,7 +38,7 @@ go(function () { //reuse $baidu->get('/duty/'); - $qq->get('/contract.shtml'); + $qq->get('/ch/tech/'); $baidu->recv(10); $qq->recv(10); Assert::same($baidu->statusCode, 200); diff --git a/tests/swoole_http_server/bug_5186.phpt b/tests/swoole_http_server/bug_5186.phpt index c6a89a874f2..b6672c216ea 100644 --- a/tests/swoole_http_server/bug_5186.phpt +++ b/tests/swoole_http_server/bug_5186.phpt @@ -1,5 +1,5 @@ --TEST-- -swoole_http_server: 在使用hyperf3的时候遇到Context::parse_multipart_data()的提示 +swoole_http_server: GitHub issue #5186 --SKIPIF-- --FILE-- diff --git a/tests/swoole_http_server/chunk.phpt b/tests/swoole_http_server/chunk.phpt index be33665b4e4..b696fa94dbd 100644 --- a/tests/swoole_http_server/chunk.phpt +++ b/tests/swoole_http_server/chunk.phpt @@ -34,9 +34,9 @@ $pm->childFunc = function () use ($pm) { $http->on("request", function (Swoole\Http\Request $request, Swoole\Http\Response $response) { $data = str_split(file_get_contents(TEST_IMAGE), 8192); foreach ($data as $chunk) { - $response->write($chunk); + Assert::true($response->write($chunk)); } - $response->end(); + Assert::true($response->end()); }); $http->start(); diff --git a/tests/swoole_http_server/reset_concurrency_with_base.phpt b/tests/swoole_http_server/reset_concurrency_with_base.phpt new file mode 100644 index 00000000000..1c3b12016a6 --- /dev/null +++ b/tests/swoole_http_server/reset_concurrency_with_base.phpt @@ -0,0 +1,90 @@ +--TEST-- +swoole_http_server: reset concurrency [SWOOLE_BASE] +--SKIPIF-- + +--FILE-- +column('pid', Table::TYPE_INT); +$table->create(); + +$pm = new SwooleTest\ProcessManager; +$pm->parentFunc = function () use ($pm) { + run(function () use ($pm) { + $n = N; + $coroutines = []; + while ($n--) { + $coroutines[] = go(function () use ($pm) { + $client = new Client('127.0.0.1', $pm->getFreePort()); + $client->set(['timeout' => 10]); + Assert::eq($client->get('/'), false); + Assert::eq($client->getStatusCode(), SWOOLE_HTTP_CLIENT_ESTATUS_SERVER_RESET); + }); + } + + Co::join($coroutines); + Co::sleep(0.1); + $client = new Client('127.0.0.1', $pm->getFreePort()); + Assert::assert($client->get('/')); + $stats = json_decode($client->getBody()); + Assert::eq($stats->concurrency, 1); + $pm->kill(); + echo "DONE\n"; + }); +}; + +$pm->childFunc = function () use ($pm, $counter, $table) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + $http->set([ + 'worker_num' => 4, + 'max_concurrency' => 160, + 'log_file' => '/dev/null', + ]); + $http->on('workerStart', function ($server, $wid) use ($pm, $table) { + if ($wid === 0) { + $pm->wakeup(); + } + $pid = posix_getpid(); + $table->set('worker_' . $wid, ['pid' => $pid]); + // echo "Worker #{$wid}(pid=$pid) is started\n"; + }); + $http->on('request', function (Request $request, Response $response) use ($http, $counter, $table) { + $c = $counter->add(); + if ($c < N) { + Co::sleep(100); + } elseif ($c == N) { + $stats = $http->stats(); + Assert::eq($stats['concurrency'], N); + $pid = posix_getpid(); + foreach ($table as $val) { + if ($val['pid'] !== $pid) { + posix_kill($val['pid'], SIGKILL); + } + } + posix_kill($pid, SIGKILL); + } else { + $stats = $http->stats(); + Assert::eq($stats['concurrency'], 1); + $response->end(json_encode($stats)); + } + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/reset_concurrency_with_process.phpt b/tests/swoole_http_server/reset_concurrency_with_process.phpt new file mode 100644 index 00000000000..97cbf5432ac --- /dev/null +++ b/tests/swoole_http_server/reset_concurrency_with_process.phpt @@ -0,0 +1,97 @@ +--TEST-- +swoole_http_server: reset concurrency [SWOOLE_PROCESS] +--SKIPIF-- + +--FILE-- +column('pid', Table::TYPE_INT); +$table->create(); + +$pm = new SwooleTest\ProcessManager; +$pm->parentFunc = function () use ($pm) { + run(function () use ($pm) { + $n = N; + $coroutines = []; + while ($n--) { + $coroutines[] = go(function () use ($pm) { + $client = new Client('127.0.0.1', $pm->getFreePort()); + $client->set(['timeout' => 10]); + Assert::eq($client->get('/'), false); + Assert::eq($client->getStatusCode(), SWOOLE_HTTP_CLIENT_ESTATUS_SERVER_RESET); + }); + } + + Co::sleep(0.1); + $pm->wait(); + + $client = new Client('127.0.0.1', $pm->getFreePort()); + Assert::assert($client->get('/')); + $stats = json_decode($client->getBody()); + Assert::eq($stats->concurrency, 1); + + /** + * PROCESS 模式下 Worker 进程退出时连接不会被关闭,这与 BASE 模式不同,因此需要先关闭服务器,其他正在运行的协程才会获得返回值 + */ + $pm->kill(); + + Co::join($coroutines); + echo "DONE\n"; + }); +}; + +$pm->childFunc = function () use ($pm, $counter, $table) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_PROCESS); + $http->set([ + 'worker_num' => 4, + 'max_concurrency' => 160, + 'log_file' => '/dev/null', + ]); + $http->on('workerStart', function ($server, $wid) use ($pm, $table) { + if ($wid === 0) { + $pm->wakeup(); + } + $pid = posix_getpid(); + $table->set('worker_' . $wid, ['pid' => $pid]); + // echo "Worker #{$wid}(pid=$pid) is started\n"; + }); + $http->on('request', function (Request $request, Response $response) use ($http, $counter, $table) { + $c = $counter->add(); + if ($c < N) { + Co::sleep(100); + } elseif ($c == N) { + $stats = $http->stats(); + Assert::eq($stats['concurrency'], N); + $pid = posix_getpid(); + foreach ($table as $val) { + if ($val['pid'] !== $pid) { + posix_kill($val['pid'], SIGKILL); + } + } + posix_kill($pid, SIGKILL); + } else { + $stats = $http->stats(); + Assert::eq($stats['concurrency'], 1); + $response->end(json_encode($stats)); + } + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/static_handler/read_link_2.phpt b/tests/swoole_http_server/static_handler/read_link_2.phpt new file mode 100644 index 00000000000..6ce49e38661 --- /dev/null +++ b/tests/swoole_http_server/static_handler/read_link_2.phpt @@ -0,0 +1,59 @@ +--TEST-- +swoole_http_server/static_handler: link to a file outside the document root +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm, $doc_root, $image_dir, $image_link) { + Swoole\Coroutine\run(function () use ($pm, $doc_root, $image_dir, $image_link) { + $data = httpGetBody("http://127.0.0.1:{$pm->getFreePort()}/{$image_dir}/image.jpg"); + Assert::assert(md5($data) === md5_file(TEST_IMAGE)); + }); + $pm->kill(); + echo "DONE\n"; +}; +$pm->childFunc = function () use ($pm, $doc_root, $image_dir, $image_link) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + $http->set([ + 'log_file' => '/dev/null', + 'open_http2_protocol' => true, + 'enable_static_handler' => true, + 'document_root' => $doc_root, + 'static_handler_locations' => ['/image'] + ]); + $http->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (Request $request, Response $response) { + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +$cleanup_fn(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/static_handler/read_link_file.phpt b/tests/swoole_http_server/static_handler/read_link_file.phpt index 14046892a45..f7bc7b2893d 100644 --- a/tests/swoole_http_server/static_handler/read_link_file.phpt +++ b/tests/swoole_http_server/static_handler/read_link_file.phpt @@ -29,7 +29,7 @@ $pm->childFunc = function () use ($pm) { 'log_file' => '/dev/null', 'open_http2_protocol' => true, 'enable_static_handler' => true, - 'document_root' => dirname(dirname(dirname(__DIR__))) . '/', + 'document_root' => dirname(__DIR__, 3) . '/', 'static_handler_locations' => ['/examples'] ]); $http->on('workerStart', function () use ($pm) { diff --git a/tests/swoole_http_server/static_handler/relative_path_2.phpt b/tests/swoole_http_server/static_handler/relative_path_2.phpt new file mode 100644 index 00000000000..26c06d14c21 --- /dev/null +++ b/tests/swoole_http_server/static_handler/relative_path_2.phpt @@ -0,0 +1,49 @@ +--TEST-- +swoole_http_server/static_handler: static handler with relative path [2] +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm) { + foreach ([false, true] as $http2) { + Swoole\Coroutine\run(function () use ($pm, $http2) { + $data = httpGetBody("http://127.0.0.1:{$pm->getFreePort()}/../examples/test.jpg", ['http2' => $http2]); + Assert::notEmpty($data); + Assert::same(md5($data), md5_file(TEST_IMAGE)); + + $data = httpGetBody("http://127.0.0.1:{$pm->getFreePort()}/../docs/swoole-logo.svg", ['http2' => $http2]); + Assert::eq("hello world", $data); + }); + } + echo "DONE\n"; + $pm->kill(); +}; +$pm->childFunc = function () use ($pm) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + $http->set([ + 'log_file' => '/dev/null', + 'open_http2_protocol' => true, + 'enable_static_handler' => true, + 'document_root' => SOURCE_ROOT_PATH . '/examples', + ]); + $http->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (Request $request, Response $response) use ($http) { + $response->end("hello world"); + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/static_handler/relative_path_3.phpt b/tests/swoole_http_server/static_handler/relative_path_3.phpt new file mode 100644 index 00000000000..a174c88cd40 --- /dev/null +++ b/tests/swoole_http_server/static_handler/relative_path_3.phpt @@ -0,0 +1,60 @@ +--TEST-- +swoole_http_server/static_handler: doc root with same prefix +--SKIPIF-- + +--FILE-- +parentFunc = function () use ($pm, $doc1_root, $doc2_root) { + Swoole\Coroutine\run(function () use ($pm, $doc1_root, $doc2_root) { + $data = httpGetBody("http://127.0.0.1:{$pm->getFreePort()}/../docroot/image.jpg"); + Assert::assert(md5($data) === md5_file(TEST_IMAGE)); + + $data = httpGetBody("http://127.0.0.1:{$pm->getFreePort()}/../docroot2/uuid.txt"); + Assert::isEmpty($data); + }); + $pm->kill(); + echo "DONE\n"; +}; +$pm->childFunc = function () use ($pm, $doc1_root, $doc2_root) { + $http = new Server('127.0.0.1', $pm->getFreePort(), SWOOLE_BASE); + $http->set([ + 'log_file' => '/dev/null', + 'open_http2_protocol' => true, + 'enable_static_handler' => true, + 'document_root' => $doc1_root, + ]); + $http->on('workerStart', function () use ($pm) { + $pm->wakeup(); + }); + $http->on('request', function (Request $request, Response $response) { + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +$cleanup_fn(); +?> +--EXPECT-- +DONE diff --git a/tests/swoole_http_server/trailer.phpt b/tests/swoole_http_server/trailer.phpt index 96ce29b7ecd..fa6710ccb12 100644 --- a/tests/swoole_http_server/trailer.phpt +++ b/tests/swoole_http_server/trailer.phpt @@ -30,9 +30,9 @@ $pm->childFunc = function () use ($pm) { $http->on('request', function (Swoole\Http\Request $request, Swoole\Http\Response $response) { $response->header('trailer', 'Content-MD5'); $data = 'hello world'; - $response->write($data); - $response->trailer('Content-MD5', md5($data)); - $response->end(); + Assert::true($response->write($data)); + Assert::true($response->trailer('Content-MD5', md5($data))); + Assert::true($response->end()); }); $http->start(); }; diff --git a/tests/swoole_pdo_oracle/bug44301.phpt b/tests/swoole_pdo_oracle/bug44301.phpt index 74a0c637fe1..4e61b2c6f76 100644 --- a/tests/swoole_pdo_oracle/bug44301.phpt +++ b/tests/swoole_pdo_oracle/bug44301.phpt @@ -28,6 +28,6 @@ run(function() { }); ?> --EXPECTF-- -SQLSTATE[HY000]: General error: 942 OCIStmtExecute: ORA-00942: table or view does not exist +SQLSTATE[HY000]: General error: 942 OCIStmtExecute: ORA-00942: table or view "SYSTEM"."NO_TABLE" does not exist Help: %s (%s:%d) diff --git a/tests/swoole_pdo_oracle/bug_33707.phpt b/tests/swoole_pdo_oracle/bug_33707.phpt index 18bfb9a02f4..6662bdd04d6 100644 --- a/tests/swoole_pdo_oracle/bug_33707.phpt +++ b/tests/swoole_pdo_oracle/bug_33707.phpt @@ -30,7 +30,7 @@ array(3) { [1]=> int(942) [2]=> - string(%d) "OCIStmtExecute: ORA-00942: table or view does not exist + string(%d) "OCIStmtExecute: ORA-00942: table or view "SYSTEM"."A_TABLE_THAT_DOES_NOT_EXIST" does not exist Help: %s (%s:%d)" } diff --git a/tests/swoole_pdo_pgsql/bug_5635.phpt b/tests/swoole_pdo_pgsql/bug_5635.phpt new file mode 100644 index 00000000000..447d4d5d05c --- /dev/null +++ b/tests/swoole_pdo_pgsql/bug_5635.phpt @@ -0,0 +1,71 @@ +--TEST-- +swoole_pdo_pgsql: Github bug #5635 +--SKIPIF-- + +--FILE-- +exec('create table bug_5635 (id int, data varchar(1024));'); +$pdo->exec(<< SWOOLE_HOOK_PDO_PGSQL]); +run(function() { + $waitGroup = new WaitGroup(); + $channel = new Channel(1); + + Coroutine::create(function() use ($waitGroup, $channel) { + $start = time(); + $waitGroup->add(); + $pdo = pdo_pgsql_test_inc::create(); + $stmt = $pdo->query("select * from bug_5635;"); + $data = $stmt->fetchAll(); + Assert::true(count($data) == 5000000); + $channel->push($data ?? [], 10); + $waitGroup->done(); + echo 'DONE' . PHP_EOL; + }); + + Coroutine::create(function() use ($waitGroup, $channel) { + $waitGroup->add(); + $result = $channel->pop(1.5); + if (!$result) { + echo 'channel pop timeout' . PHP_EOL; + } + $waitGroup->done(); + }); + + var_dump(1); + Coroutine::sleep(1); + var_dump(2); + $waitGroup->wait(); +}); +?> +--CLEAN-- +exec('drop table bug_5635;'); +?> +--EXPECTF-- +int(1) +int(2) +channel pop timeout +DONE diff --git a/tests/swoole_runtime/capture_peer_cert.phpt b/tests/swoole_runtime/ssl/capture_peer_cert.phpt similarity index 100% rename from tests/swoole_runtime/capture_peer_cert.phpt rename to tests/swoole_runtime/ssl/capture_peer_cert.phpt diff --git a/tests/swoole_runtime/ssl_client.phpt b/tests/swoole_runtime/ssl/client.phpt similarity index 100% rename from tests/swoole_runtime/ssl_client.phpt rename to tests/swoole_runtime/ssl/client.phpt diff --git a/tests/swoole_runtime/ssl/enable_crypto.phpt b/tests/swoole_runtime/ssl/enable_crypto.phpt new file mode 100644 index 00000000000..649eed7e6ce --- /dev/null +++ b/tests/swoole_runtime/ssl/enable_crypto.phpt @@ -0,0 +1,54 @@ +--TEST-- +swoole_runtime/ssl: stream_socket_enable_crypto +--SKIPIF-- + +--FILE-- +\n"; + } else { + $ready->push(true); + $conn = stream_socket_accept($socket); + fwrite($conn, 'The local time is ' . date('n/j/Y g:i a')); + fclose($conn); + fclose($socket); + echo "OK\n"; + } +}); +go(function () use ($ready) { + $ready->pop(); + $fp = stream_socket_client("tcp://127.0.0.1:8000", $errno, $errstr, 30); + if (!$fp) { + echo "$errstr ($errno)
\n"; + } else { + stream_context_set_option($fp, ["ssl" => [ + "local_cert" => SSL_FILE_DIR . '/client.crt', + "local_pk" => SSL_FILE_DIR . '/client.key', + ]]); + // Enable SSL encryption after the connection is established + Assert::assert(stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)); + $data = fread($fp, 8192); + fclose($fp); + Assert::assert(strpos($data, 'local time') !== false); + echo "OK\n"; + } +}); +Swoole\Event::wait(); +?> +--EXPECT-- +OK +OK diff --git a/tests/swoole_runtime/ssl_server.phpt b/tests/swoole_runtime/ssl/server.phpt similarity index 100% rename from tests/swoole_runtime/ssl_server.phpt rename to tests/swoole_runtime/ssl/server.phpt diff --git a/tests/swoole_server/memory_leak/task.phpt b/tests/swoole_server/memory_leak/task.phpt index 2ca7ab31cdd..aaa238f0d05 100644 --- a/tests/swoole_server/memory_leak/task.phpt +++ b/tests/swoole_server/memory_leak/task.phpt @@ -15,6 +15,7 @@ $pm = new SwooleTest\ProcessManager; $GLOBALS['counter1'] = 0; $GLOBALS['counter2'] = 0; +$GLOBALS['atomic'] = new Swoole\Atomic; $n = MAX_REQUESTS; $chunks = []; @@ -57,10 +58,11 @@ $pm->childFunc = function () use ($pm, $total, $chunks) { 'task_worker_num' => 1, 'log_file' => '/dev/null', )); - $serv->on("WorkerStart", function (Server $serv, $wid) use ($pm) { + $serv->on('WorkerStart', function (Server $serv, $wid) use ($pm) { if ($wid == 0) { $pm->wakeup(); } + $GLOBALS['atomic']->add(); }); $serv->on('receive', function (Server $serv, $fd, $rid, $_data) use ($chunks) { foreach ($chunks as $ch) { @@ -82,6 +84,7 @@ $pm->childFunc = function () use ($pm, $total, $chunks) { $GLOBALS['memory_usage_2'] = memory_get_usage(); Assert::lessThan($GLOBALS['memory_usage_2'] - $GLOBALS['memory_usage_1'], 8192); Assert::eq($GLOBALS['counter2'], $total); + $GLOBALS['atomic']->add(); echo "DONE\n"; }); $serv->start(); @@ -89,6 +92,8 @@ $pm->childFunc = function () use ($pm, $total, $chunks) { $pm->childFirst(); $pm->run(); +Assert::eq($GLOBALS['atomic']->get(), 4); ?> --EXPECT-- DONE +DONE diff --git a/tests/swoole_server/named_parameters.phpt b/tests/swoole_server/named_parameters.phpt new file mode 100644 index 00000000000..c5f433aabc0 --- /dev/null +++ b/tests/swoole_server/named_parameters.phpt @@ -0,0 +1,46 @@ +--TEST-- +swoole_server: new twice +--SKIPIF-- + +--FILE-- +parentFunc = function ($pid) use ($pm, $atomic) { + posix_kill($atomic->get(), SIGINT); + $pm->wait(); + $pm->kill(); +}; +$pm->childFunc = function () use ($pm, $atomic) { + $http = new Server('0.0.0.0', 9501, SWOOLE_PROCESS); + $http->set([ + Constant::OPTION_WORKER_NUM => 1 + ]); + $http->on('WorkerStart', function () use ($pm, $http, $atomic) { + if ($atomic->get() == 0) { + $atomic->set(posix_getpid()); + Event::defer(function () use ($pm) { + $pm->wakeup(); + }); + Swoole\Coroutine\System::waitSignal(SIGINT); + var_dump($http->stop(waitEvent: true), $http->getLastError()); + } else { + $pm->wakeup(); + } + }); + $http->on('request', function () { + }); + $http->start(); +}; +$pm->childFirst(); +$pm->run(); +?> +--EXPECT-- +bool(true) +int(0) diff --git a/tests/swoole_server/parse_option_to_size.phpt b/tests/swoole_server/parse_option_to_size.phpt new file mode 100644 index 00000000000..25700d05cae --- /dev/null +++ b/tests/swoole_server/parse_option_to_size.phpt @@ -0,0 +1,28 @@ +--TEST-- +swoole_server: parse option value to size +--SKIPIF-- + +--FILE-- +set([ + 'buffer_output_size' => '2M', +]); +$server->set([ + 'buffer_output_size' => 2 * 1024 * 1024, +]); +$server->set([ + 'buffer_output_size' => 'xxx--2M', +]); +?> +--EXPECTF-- +Fatal error: Swoole\Server::set(): failed to parse 'xxx--2M' to size, Error: Invalid quantity "xxx--2M": no valid leading digits, interpreting as "0" for backwards compatibility in %s on line %d diff --git a/tests/swoole_server_coro/ssl.phpt b/tests/swoole_server_coro/ssl.phpt index ea747b9a5c8..497fed99155 100644 --- a/tests/swoole_server_coro/ssl.phpt +++ b/tests/swoole_server_coro/ssl.phpt @@ -13,8 +13,7 @@ $pm = new ProcessManager; $pm->parentFunc = function ($pid) use ($pm) { $client = new Swoole\Client(SWOOLE_SOCK_TCP | SWOOLE_SSL, SWOOLE_SOCK_SYNC); //同步阻塞 - if (!$client->connect('127.0.0.1', $pm->getFreePort())) - { + if (!$client->connect('127.0.0.1', $pm->getFreePort())) { exit("connect failed\n"); } $client->send("hello world"); diff --git a/thirdparty/php/curl/curl_arginfo.h b/thirdparty/php/curl/curl_arginfo.h index 383716f0816..39e14ba2ce6 100644 --- a/thirdparty/php/curl/curl_arginfo.h +++ b/thirdparty/php/curl/curl_arginfo.h @@ -32,12 +32,6 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_swoole_native_curl_exec, 0, 1, M ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_swoole_native_curl_file_create, 0, 1, CURLFile, 0) - ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, mime_type, IS_STRING, 1, "null") - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, posted_filename, IS_STRING, 1, "null") -ZEND_END_ARG_INFO() - ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_getinfo, 0, 1, IS_MIXED, 0) ZEND_ARG_OBJ_INFO(0, handle, CurlHandle, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, option, IS_LONG, 1, "null") diff --git a/thirdparty/php/curl/curl_private.h b/thirdparty/php/curl/curl_private.h index b8be8932b59..50c782485c6 100644 --- a/thirdparty/php/curl/curl_private.h +++ b/thirdparty/php/curl/curl_private.h @@ -203,7 +203,7 @@ static inline php_curlsh *curl_share_from_obj(zend_object *obj) { } #define Z_CURL_SHARE_P(zv) curl_share_from_obj(Z_OBJ_P(zv)) -void curl_multi_register_class(const zend_function_entry *method_entries); +void swoole_curl_multi_register_handlers(void); curl_result_t swoole_curl_cast_object(zend_object *obj, zval *result, int type); php_curl *swoole_curl_get_handle(zval *zid, bool exclusive = true, bool required = true); diff --git a/thirdparty/php/curl/interface.cc b/thirdparty/php/curl/interface.cc index a70a63ee3ac..f3142b19349 100644 --- a/thirdparty/php/curl/interface.cc +++ b/thirdparty/php/curl/interface.cc @@ -261,6 +261,9 @@ void swoole_native_curl_minit(int module_number) { } swoole_coroutine_curl_handle_ce = curl_ce; swoole_coroutine_curl_handle_ce->create_object = swoole_curl_create_object; +#if PHP_VERSION_ID >= 80300 + swoole_coroutine_curl_handle_ce->default_object_handlers = &swoole_coroutine_curl_handle_handlers; +#endif memcpy(&swoole_coroutine_curl_handle_handlers, &std_object_handlers, sizeof(zend_object_handlers)); swoole_coroutine_curl_handle_handlers.offset = XtOffsetOf(php_curl, std); swoole_coroutine_curl_handle_handlers.free_obj = swoole_curl_free_obj; @@ -274,7 +277,7 @@ void swoole_native_curl_minit(int module_number) { zend_declare_property_null(swoole_coroutine_curl_handle_ce, ZEND_STRL("private_data"), ZEND_ACC_PUBLIC); - curl_multi_register_class(nullptr); + swoole_curl_multi_register_handlers(); zend_unregister_functions(swoole_native_curl_functions, -1, CG(function_table)); zend_register_functions(NULL, swoole_native_curl_functions, NULL, MODULE_PERSISTENT); @@ -293,7 +296,9 @@ static zend_object *swoole_curl_create_object(zend_class_entry *class_type) { zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); +#if PHP_VERSION_ID < 80300 intern->std.handlers = &swoole_coroutine_curl_handle_handlers; +#endif return &intern->std; } @@ -907,10 +912,6 @@ void swoole_curl_init_handle(php_curl *ch) { zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t) curl_free_post, 0); zend_llist_init(&ch->to_free->stream, sizeof(struct mime_data_cb_arg *), (llist_dtor_func_t) curl_free_cb_arg, 0); -#if LIBCURL_VERSION_NUM < 0x073800 && PHP_VERSION_ID >= 80100 - zend_llist_init(&ch->to_free->buffers, sizeof(zend_string *), (llist_dtor_func_t)curl_free_buffers, 0); -#endif - ch->to_free->slist = (HashTable *) emalloc(sizeof(HashTable)); zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0); ZVAL_UNDEF(&ch->postfields); @@ -2444,10 +2445,6 @@ static void _php_curl_free(php_curl *ch) { if (--(*ch->clone) == 0) { #if PHP_VERSION_ID < 80100 zend_llist_clean(&ch->to_free->str); -#else -#if LIBCURL_VERSION_NUM < 0x073800 /* 7.56.0 */ - zend_llist_clean(&ch->to_free->buffers); -#endif #endif zend_llist_clean(&ch->to_free->post); zend_llist_clean(&ch->to_free->stream); diff --git a/thirdparty/php/curl/multi.cc b/thirdparty/php/curl/multi.cc index 52f6ccb6931..9dc0f9f1337 100644 --- a/thirdparty/php/curl/multi.cc +++ b/thirdparty/php/curl/multi.cc @@ -551,7 +551,9 @@ static zend_object *swoole_curl_multi_create_object(zend_class_entry *class_type zend_object_std_init(&intern->std, class_type); object_properties_init(&intern->std, class_type); +#if PHP_VERSION_ID < 80300 intern->std.handlers = &swoole_coroutine_curl_multi_handle_handlers; +#endif return &intern->std; } @@ -600,9 +602,12 @@ static HashTable *swoole_curl_multi_get_gc(zend_object *object, zval **table, in return zend_std_get_properties(object); } -void curl_multi_register_class(const zend_function_entry *method_entries) { +void swoole_curl_multi_register_handlers(void) { swoole_coroutine_curl_multi_handle_ce = curl_multi_ce; swoole_coroutine_curl_multi_handle_ce->create_object = swoole_curl_multi_create_object; +#if PHP_VERSION_ID >= 80300 + swoole_coroutine_curl_multi_handle_ce->default_object_handlers = &swoole_coroutine_curl_multi_handle_handlers; +#endif memcpy(&swoole_coroutine_curl_multi_handle_handlers, &std_object_handlers, sizeof(zend_object_handlers)); swoole_coroutine_curl_multi_handle_handlers.offset = XtOffsetOf(php_curlm, std); diff --git a/thirdparty/php80/pdo_oci/oci_driver.c b/thirdparty/php80/pdo_oci/oci_driver.c index cba6c1bb865..370401c4b49 100644 --- a/thirdparty/php80/pdo_oci/oci_driver.c +++ b/thirdparty/php80/pdo_oci/oci_driver.c @@ -17,7 +17,7 @@ #define SW_USE_ORACLE_HOOK #include "php_swoole_oracle.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_ORACLE) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php80/pdo_oci/oci_statement.c b/thirdparty/php80/pdo_oci/oci_statement.c index 5e4ae72c12a..12b1ad5e262 100644 --- a/thirdparty/php80/pdo_oci/oci_statement.c +++ b/thirdparty/php80/pdo_oci/oci_statement.c @@ -17,7 +17,7 @@ #define SW_USE_ORACLE_HOOK #include "php_swoole_oracle.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_ORACLE) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php80/pdo_oci/php_pdo_oci_int.h b/thirdparty/php80/pdo_oci/php_pdo_oci_int.h index b8d671b2ad6..1aa178f8a64 100644 --- a/thirdparty/php80/pdo_oci/php_pdo_oci_int.h +++ b/thirdparty/php80/pdo_oci/php_pdo_oci_int.h @@ -17,79 +17,78 @@ #include typedef struct { - const char *file; - int line; - sb4 errcode; - char *errmsg; + const char *file; + int line; + sb4 errcode; + char *errmsg; } pdo_oci_error_info; /* stuff we use in an OCI database handle */ typedef struct { - OCIServer *server; - OCISession *session; - OCIEnv *env; - OCIError *err; - OCISvcCtx *svc; - /* OCI9; 0 == use NLS_LANG */ - ub4 prefetch; - ub2 charset; - sword last_err; - sb4 max_char_width; - - unsigned attached:1; - unsigned _reserved:31; - - pdo_oci_error_info einfo; + OCIServer *server; + OCISession *session; + OCIEnv *env; + OCIError *err; + OCISvcCtx *svc; + /* OCI9; 0 == use NLS_LANG */ + ub4 prefetch; + ub2 charset; + sword last_err; + sb4 max_char_width; + + unsigned attached : 1; + unsigned _reserved : 31; + + pdo_oci_error_info einfo; } pdo_oci_db_handle; typedef struct { - OCIDefine *def; - ub2 fetched_len; - ub2 retcode; - sb2 indicator; + OCIDefine *def; + ub2 fetched_len; + ub2 retcode; + sb2 indicator; - char *data; - ub4 datalen; + char *data; + ub4 datalen; - ub2 dtype; + ub2 dtype; } pdo_oci_column; typedef struct { - pdo_oci_db_handle *H; - OCIStmt *stmt; - OCIError *err; - sword last_err; - ub2 stmt_type; - ub4 exec_type; - pdo_oci_column *cols; - pdo_oci_error_info einfo; - unsigned int have_blobs:1; + pdo_oci_db_handle *H; + OCIStmt *stmt; + OCIError *err; + sword last_err; + ub2 stmt_type; + ub4 exec_type; + pdo_oci_column *cols; + pdo_oci_error_info einfo; + unsigned int have_blobs : 1; } pdo_oci_stmt; typedef struct { - OCIBind *bind; /* allocated by OCI */ - sb2 oci_type; - sb2 indicator; - ub2 retcode; + OCIBind *bind; /* allocated by OCI */ + sb2 oci_type; + sb2 indicator; + ub2 retcode; - ub4 actual_len; + ub4 actual_len; - dvoid *thing; /* for LOBS, REFCURSORS etc. */ + dvoid *thing; /* for LOBS, REFCURSORS etc. */ - unsigned used_for_output; + unsigned used_for_output; } pdo_oci_bound_param; extern const struct pdo_stmt_methods swoole_oci_stmt_methods; extern const ub4 SWOOLE_PDO_OCI_INIT_MODE; extern OCIEnv *swoole_pdo_oci_Env; -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line); -#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__) -#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__) -#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__) - -extern const struct pdo_stmt_methods oci_stmt_methods; +ub4 _oci_error( + OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line); +#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__) +#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__) +#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__) /* Default prefetch size in number of rows */ #define PDO_OCI_PREFETCH_DEFAULT 100 @@ -97,11 +96,10 @@ extern const struct pdo_stmt_methods oci_stmt_methods; /* Arbitrary assumed row length for prefetch memory limit calcuation */ #define PDO_OCI_PREFETCH_ROWSIZE 1024 - enum { - PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC, - PDO_OCI_ATTR_CLIENT_INFO, - PDO_OCI_ATTR_CLIENT_IDENTIFIER, - PDO_OCI_ATTR_MODULE, - PDO_OCI_ATTR_CALL_TIMEOUT + PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC, + PDO_OCI_ATTR_CLIENT_INFO, + PDO_OCI_ATTR_CLIENT_IDENTIFIER, + PDO_OCI_ATTR_MODULE, + PDO_OCI_ATTR_CALL_TIMEOUT }; diff --git a/thirdparty/php80/pdo_odbc/odbc_driver.c b/thirdparty/php80/pdo_odbc/odbc_driver.c index 2c666cc2104..0e7c7b9722c 100644 --- a/thirdparty/php80/pdo_odbc/odbc_driver.c +++ b/thirdparty/php80/pdo_odbc/odbc_driver.c @@ -17,7 +17,7 @@ #define SW_USE_ODBC_HOOK #include "php_swoole_odbc.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_ODBC) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php80/pdo_odbc/odbc_stmt.c b/thirdparty/php80/pdo_odbc/odbc_stmt.c index 12a1bb203c8..b814cc6b8f5 100644 --- a/thirdparty/php80/pdo_odbc/odbc_stmt.c +++ b/thirdparty/php80/pdo_odbc/odbc_stmt.c @@ -17,7 +17,7 @@ #define SW_USE_ODBC_HOOK #include "php_swoole_odbc.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_ODBC) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php80/pdo_pgsql/pgsql_driver.c b/thirdparty/php80/pdo_pgsql/pgsql_driver.c index 34661423741..2474af62045 100644 --- a/thirdparty/php80/pdo_pgsql/pgsql_driver.c +++ b/thirdparty/php80/pdo_pgsql/pgsql_driver.c @@ -19,7 +19,7 @@ #define SW_USE_PGSQL_HOOK #include "php_swoole_pgsql.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_PGSQL) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php80/pdo_pgsql/pgsql_statement.c b/thirdparty/php80/pdo_pgsql/pgsql_statement.c index 6bb17aaad4f..4e54cfee27d 100644 --- a/thirdparty/php80/pdo_pgsql/pgsql_statement.c +++ b/thirdparty/php80/pdo_pgsql/pgsql_statement.c @@ -19,7 +19,7 @@ #define SW_USE_PGSQL_HOOK #include "php_swoole_pgsql.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_PGSQL) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php80/pdo_sqlite/sqlite_driver.c b/thirdparty/php80/pdo_sqlite/sqlite_driver.c index 21d66d0f7d3..ea9b3dd3b13 100644 --- a/thirdparty/php80/pdo_sqlite/sqlite_driver.c +++ b/thirdparty/php80/pdo_sqlite/sqlite_driver.c @@ -17,7 +17,7 @@ #define SW_USE_SQLITE_HOOK #include "php_swoole_sqlite.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_SQLITE) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php80/pdo_sqlite/sqlite_statement.c b/thirdparty/php80/pdo_sqlite/sqlite_statement.c index ca94200a679..5864d1ec39a 100644 --- a/thirdparty/php80/pdo_sqlite/sqlite_statement.c +++ b/thirdparty/php80/pdo_sqlite/sqlite_statement.c @@ -17,7 +17,7 @@ #define SW_USE_SQLITE_HOOK #include "php_swoole_sqlite.h" -#if PHP_VERSION_ID < 80100 +#if defined(SW_USE_SQLITE) && PHP_VERSION_ID < 80100 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php81/pdo_oci/oci_driver.c b/thirdparty/php81/pdo_oci/oci_driver.c index 8f0207c2eb4..56ea3608911 100644 --- a/thirdparty/php81/pdo_oci/oci_driver.c +++ b/thirdparty/php81/pdo_oci/oci_driver.c @@ -17,7 +17,7 @@ #define SW_USE_ORACLE_HOOK #include "php_swoole_oracle.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_ORACLE) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php81/pdo_oci/oci_statement.c b/thirdparty/php81/pdo_oci/oci_statement.c index c32afea10c5..0f585c65eb6 100644 --- a/thirdparty/php81/pdo_oci/oci_statement.c +++ b/thirdparty/php81/pdo_oci/oci_statement.c @@ -16,7 +16,7 @@ #define SW_USE_ORACLE_HOOK #include "php_swoole_oracle.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_ORACLE) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php81/pdo_oci/php_pdo_oci_int.h b/thirdparty/php81/pdo_oci/php_pdo_oci_int.h index 2d3db8f7309..6668c108d79 100644 --- a/thirdparty/php81/pdo_oci/php_pdo_oci_int.h +++ b/thirdparty/php81/pdo_oci/php_pdo_oci_int.h @@ -17,73 +17,74 @@ #include typedef struct { - const char *file; - int line; - sb4 errcode; - char *errmsg; + const char *file; + int line; + sb4 errcode; + char *errmsg; } pdo_oci_error_info; /* stuff we use in an OCI database handle */ typedef struct { - OCIServer *server; - OCISession *session; - OCIEnv *env; - OCIError *err; - OCISvcCtx *svc; - /* OCI9; 0 == use NLS_LANG */ - ub4 prefetch; - ub2 charset; - sword last_err; - sb4 max_char_width; - - unsigned attached:1; - unsigned _reserved:31; - - pdo_oci_error_info einfo; + OCIServer *server; + OCISession *session; + OCIEnv *env; + OCIError *err; + OCISvcCtx *svc; + /* OCI9; 0 == use NLS_LANG */ + ub4 prefetch; + ub2 charset; + sword last_err; + sb4 max_char_width; + + unsigned attached : 1; + unsigned _reserved : 31; + + pdo_oci_error_info einfo; } pdo_oci_db_handle; typedef struct { - OCIDefine *def; - ub2 fetched_len; - ub2 retcode; - sb2 indicator; + OCIDefine *def; + ub2 fetched_len; + ub2 retcode; + sb2 indicator; - char *data; - ub4 datalen; + char *data; + ub4 datalen; - ub2 dtype; + ub2 dtype; } pdo_oci_column; typedef struct { - pdo_oci_db_handle *H; - OCIStmt *stmt; - OCIError *err; - sword last_err; - ub2 stmt_type; - ub4 exec_type; - pdo_oci_column *cols; - pdo_oci_error_info einfo; - unsigned int have_blobs:1; + pdo_oci_db_handle *H; + OCIStmt *stmt; + OCIError *err; + sword last_err; + ub2 stmt_type; + ub4 exec_type; + pdo_oci_column *cols; + pdo_oci_error_info einfo; + unsigned int have_blobs : 1; } pdo_oci_stmt; typedef struct { - OCIBind *bind; /* allocated by OCI */ - sb2 oci_type; - sb2 indicator; - ub2 retcode; + OCIBind *bind; /* allocated by OCI */ + sb2 oci_type; + sb2 indicator; + ub2 retcode; - ub4 actual_len; + ub4 actual_len; - dvoid *thing; /* for LOBS, REFCURSORS etc. */ + dvoid *thing; /* for LOBS, REFCURSORS etc. */ - unsigned used_for_output; + unsigned used_for_output; } pdo_oci_bound_param; -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line); -#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__) -#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__) -#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__) +ub4 _oci_error( + OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line); +#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__) +#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__) +#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__) extern const struct pdo_stmt_methods swoole_oci_stmt_methods; extern const ub4 SWOOLE_PDO_OCI_INIT_MODE; @@ -95,11 +96,10 @@ extern OCIEnv *swoole_pdo_oci_Env; /* Arbitrary assumed row length for prefetch memory limit calcuation */ #define PDO_OCI_PREFETCH_ROWSIZE 1024 - enum { - PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC, - PDO_OCI_ATTR_CLIENT_INFO, - PDO_OCI_ATTR_CLIENT_IDENTIFIER, - PDO_OCI_ATTR_MODULE, - PDO_OCI_ATTR_CALL_TIMEOUT + PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC, + PDO_OCI_ATTR_CLIENT_INFO, + PDO_OCI_ATTR_CLIENT_IDENTIFIER, + PDO_OCI_ATTR_MODULE, + PDO_OCI_ATTR_CALL_TIMEOUT }; diff --git a/thirdparty/php81/pdo_odbc/odbc_driver.c b/thirdparty/php81/pdo_odbc/odbc_driver.c index 26bb8e5f682..16a49ce40e2 100644 --- a/thirdparty/php81/pdo_odbc/odbc_driver.c +++ b/thirdparty/php81/pdo_odbc/odbc_driver.c @@ -17,7 +17,7 @@ #define SW_USE_ODBC_HOOK #include "php_swoole_odbc.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_ODBC) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php81/pdo_odbc/odbc_stmt.c b/thirdparty/php81/pdo_odbc/odbc_stmt.c index cbb0d3cdff1..0daf33fffd8 100644 --- a/thirdparty/php81/pdo_odbc/odbc_stmt.c +++ b/thirdparty/php81/pdo_odbc/odbc_stmt.c @@ -17,7 +17,7 @@ #define SW_USE_ODBC_HOOK #include "php_swoole_odbc.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_ODBC) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php81/pdo_pgsql/pgsql_driver.c b/thirdparty/php81/pdo_pgsql/pgsql_driver.c index c65d29d8bd8..556565add4a 100644 --- a/thirdparty/php81/pdo_pgsql/pgsql_driver.c +++ b/thirdparty/php81/pdo_pgsql/pgsql_driver.c @@ -19,7 +19,7 @@ #define SW_USE_PGSQL_HOOK #include "php_swoole_pgsql.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_PGSQL) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php81/pdo_pgsql/pgsql_statement.c b/thirdparty/php81/pdo_pgsql/pgsql_statement.c index f1b958e53f1..263b9398af0 100644 --- a/thirdparty/php81/pdo_pgsql/pgsql_statement.c +++ b/thirdparty/php81/pdo_pgsql/pgsql_statement.c @@ -19,7 +19,7 @@ #define SW_USE_PGSQL_HOOK #include "php_swoole_pgsql.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_PGSQL) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php81/pdo_sqlite/sqlite_driver.c b/thirdparty/php81/pdo_sqlite/sqlite_driver.c index 61f6948a202..fd262ee45fa 100644 --- a/thirdparty/php81/pdo_sqlite/sqlite_driver.c +++ b/thirdparty/php81/pdo_sqlite/sqlite_driver.c @@ -16,7 +16,7 @@ #define SW_USE_SQLITE_HOOK #include "php_swoole_sqlite.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_SQLITE) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php81/pdo_sqlite/sqlite_statement.c b/thirdparty/php81/pdo_sqlite/sqlite_statement.c index 9081cbb7788..ec22bee92b6 100644 --- a/thirdparty/php81/pdo_sqlite/sqlite_statement.c +++ b/thirdparty/php81/pdo_sqlite/sqlite_statement.c @@ -17,7 +17,7 @@ #define SW_USE_SQLITE_HOOK #include "php_swoole_sqlite.h" -#if PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 +#if defined(SW_USE_SQLITE) && PHP_VERSION_ID >= 80100 && PHP_VERSION_ID < 80300 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php83/pdo_oci/oci_driver.c b/thirdparty/php83/pdo_oci/oci_driver.c index d1ca6d69c75..52f6bc37ec8 100644 --- a/thirdparty/php83/pdo_oci/oci_driver.c +++ b/thirdparty/php83/pdo_oci/oci_driver.c @@ -17,7 +17,7 @@ #define SW_USE_ORACLE_HOOK #include "php_swoole_oracle.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_ORACLE) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php83/pdo_oci/oci_statement.c b/thirdparty/php83/pdo_oci/oci_statement.c index d048a91217c..6ce3b4ca765 100644 --- a/thirdparty/php83/pdo_oci/oci_statement.c +++ b/thirdparty/php83/pdo_oci/oci_statement.c @@ -17,7 +17,7 @@ #define SW_USE_ORACLE_HOOK #include "php_swoole_oracle.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_ORACLE) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php83/pdo_oci/php_pdo_oci_int.h b/thirdparty/php83/pdo_oci/php_pdo_oci_int.h index a455188c924..0e693c0e459 100644 --- a/thirdparty/php83/pdo_oci/php_pdo_oci_int.h +++ b/thirdparty/php83/pdo_oci/php_pdo_oci_int.h @@ -14,87 +14,81 @@ +----------------------------------------------------------------------+ */ -#ifndef PHP_PDO_OCI_INT_H -#define PHP_PDO_OCI_INT_H - -#include "zend_portability.h" - -ZEND_DIAGNOSTIC_IGNORED_START("-Wstrict-prototypes") #include -ZEND_DIAGNOSTIC_IGNORED_END typedef struct { - const char *file; - int line; - sb4 errcode; - char *errmsg; + const char *file; + int line; + sb4 errcode; + char *errmsg; } pdo_oci_error_info; /* stuff we use in an OCI database handle */ typedef struct { - OCIServer *server; - OCISession *session; - OCIEnv *env; - OCIError *err; - OCISvcCtx *svc; - /* OCI9; 0 == use NLS_LANG */ - ub4 prefetch; - ub2 charset; - sword last_err; - sb4 max_char_width; - - unsigned attached:1; - unsigned _reserved:31; - - pdo_oci_error_info einfo; + OCIServer *server; + OCISession *session; + OCIEnv *env; + OCIError *err; + OCISvcCtx *svc; + /* OCI9; 0 == use NLS_LANG */ + ub4 prefetch; + ub2 charset; + sword last_err; + sb4 max_char_width; + + unsigned attached : 1; + unsigned _reserved : 31; + + pdo_oci_error_info einfo; } pdo_oci_db_handle; typedef struct { - OCIDefine *def; - ub2 fetched_len; - ub2 retcode; - sb2 indicator; + OCIDefine *def; + ub2 fetched_len; + ub2 retcode; + sb2 indicator; - char *data; - ub4 datalen; + char *data; + ub4 datalen; - ub2 dtype; + ub2 dtype; } pdo_oci_column; typedef struct { - pdo_oci_db_handle *H; - OCIStmt *stmt; - OCIError *err; - sword last_err; - ub2 stmt_type; - ub4 exec_type; - pdo_oci_column *cols; - pdo_oci_error_info einfo; - unsigned int have_blobs:1; + pdo_oci_db_handle *H; + OCIStmt *stmt; + OCIError *err; + sword last_err; + ub2 stmt_type; + ub4 exec_type; + pdo_oci_column *cols; + pdo_oci_error_info einfo; + unsigned int have_blobs : 1; } pdo_oci_stmt; typedef struct { - OCIBind *bind; /* allocated by OCI */ - sb2 oci_type; - sb2 indicator; - ub2 retcode; + OCIBind *bind; /* allocated by OCI */ + sb2 oci_type; + sb2 indicator; + ub2 retcode; - ub4 actual_len; + ub4 actual_len; - dvoid *thing; /* for LOBS, REFCURSORS etc. */ + dvoid *thing; /* for LOBS, REFCURSORS etc. */ - unsigned used_for_output; + unsigned used_for_output; } pdo_oci_bound_param; -extern const ub4 PDO_OCI_INIT_MODE; -extern const pdo_driver_t pdo_oci_driver; -extern OCIEnv *pdo_oci_Env; +extern const ub4 SWOOLE_PDO_OCI_INIT_MODE; +extern const pdo_driver_t swoole_pdo_oci_driver; +extern OCIEnv *swoole_pdo_oci_Env; -ub4 _oci_error(OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line); -#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__) -#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__) -#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__) +ub4 _oci_error( + OCIError *err, pdo_dbh_t *dbh, pdo_stmt_t *stmt, char *what, sword status, int isinit, const char *file, int line); +#define oci_init_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, TRUE, __FILE__, __LINE__) +#define oci_drv_error(w) _oci_error(H->err, dbh, NULL, w, H->last_err, FALSE, __FILE__, __LINE__) +#define oci_stmt_error(w) _oci_error(S->err, stmt->dbh, stmt, w, S->last_err, FALSE, __FILE__, __LINE__) extern const struct pdo_stmt_methods swoole_oci_stmt_methods; extern const ub4 SWOOLE_PDO_OCI_INIT_MODE; @@ -106,13 +100,10 @@ extern OCIEnv *swoole_pdo_oci_Env; /* Arbitrary assumed row length for prefetch memory limit calcuation */ #define PDO_OCI_PREFETCH_ROWSIZE 1024 - enum { - PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC, - PDO_OCI_ATTR_CLIENT_INFO, - PDO_OCI_ATTR_CLIENT_IDENTIFIER, - PDO_OCI_ATTR_MODULE, - PDO_OCI_ATTR_CALL_TIMEOUT + PDO_OCI_ATTR_ACTION = PDO_ATTR_DRIVER_SPECIFIC, + PDO_OCI_ATTR_CLIENT_INFO, + PDO_OCI_ATTR_CLIENT_IDENTIFIER, + PDO_OCI_ATTR_MODULE, + PDO_OCI_ATTR_CALL_TIMEOUT }; - -#endif /* PHP_PDO_OCI_INT_H */ diff --git a/thirdparty/php83/pdo_odbc/odbc_driver.c b/thirdparty/php83/pdo_odbc/odbc_driver.c index a5e3a8b4f0c..337d38cb3be 100644 --- a/thirdparty/php83/pdo_odbc/odbc_driver.c +++ b/thirdparty/php83/pdo_odbc/odbc_driver.c @@ -17,7 +17,7 @@ #define SW_USE_ODBC_HOOK #include "php_swoole_odbc.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_ODBC) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php83/pdo_odbc/odbc_stmt.c b/thirdparty/php83/pdo_odbc/odbc_stmt.c index c8eef615784..a34570e801d 100644 --- a/thirdparty/php83/pdo_odbc/odbc_stmt.c +++ b/thirdparty/php83/pdo_odbc/odbc_stmt.c @@ -17,8 +17,7 @@ #define SW_USE_ODBC_HOOK #include "php_swoole_odbc.h" -#if PHP_VERSION_ID >= 80300 - +#if defined(SW_USE_ODBC) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php83/pdo_pgsql/pgsql_driver.c b/thirdparty/php83/pdo_pgsql/pgsql_driver.c index 73e610674a4..a1946c49628 100644 --- a/thirdparty/php83/pdo_pgsql/pgsql_driver.c +++ b/thirdparty/php83/pdo_pgsql/pgsql_driver.c @@ -19,7 +19,7 @@ #define SW_USE_PGSQL_HOOK #include "php_swoole_pgsql.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_PGSQL) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php83/pdo_pgsql/pgsql_statement.c b/thirdparty/php83/pdo_pgsql/pgsql_statement.c index 13532fe3659..0914b50f251 100644 --- a/thirdparty/php83/pdo_pgsql/pgsql_statement.c +++ b/thirdparty/php83/pdo_pgsql/pgsql_statement.c @@ -19,7 +19,7 @@ #define SW_USE_PGSQL_HOOK #include "php_swoole_pgsql.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_PGSQL) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" diff --git a/thirdparty/php83/pdo_sqlite/sqlite_driver.c b/thirdparty/php83/pdo_sqlite/sqlite_driver.c index e130d779f9c..cd363714f94 100644 --- a/thirdparty/php83/pdo_sqlite/sqlite_driver.c +++ b/thirdparty/php83/pdo_sqlite/sqlite_driver.c @@ -17,7 +17,7 @@ #include "php_swoole_sqlite.h" #include "php_swoole_call_stack.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_SQLITE) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h" diff --git a/thirdparty/php83/pdo_sqlite/sqlite_statement.c b/thirdparty/php83/pdo_sqlite/sqlite_statement.c index 52fa33b2abb..7355b9dd39d 100644 --- a/thirdparty/php83/pdo_sqlite/sqlite_statement.c +++ b/thirdparty/php83/pdo_sqlite/sqlite_statement.c @@ -17,7 +17,7 @@ #define SW_USE_SQLITE_HOOK #include "php_swoole_sqlite.h" -#if PHP_VERSION_ID >= 80300 +#if defined(SW_USE_SQLITE) && PHP_VERSION_ID >= 80300 #include "php.h" #include "php_ini.h" #include "ext/standard/info.h"