diff --git a/core-tests/src/core/base.cpp b/core-tests/src/core/base.cpp index 1c9528d8827..f0c411d33ab 100644 --- a/core-tests/src/core/base.cpp +++ b/core-tests/src/core/base.cpp @@ -223,17 +223,6 @@ static std::string test_func(std::string test_data_2) { return test_data + test_data_2; } -TEST(base, add_function) { - typedef std::string (*_func_t)(std::string); - swoole_add_function("test_func", (void *) test_func); - ASSERT_EQ(swoole_add_function("test_func", (void *) test_func), SW_ERR); - _func_t _func = (_func_t) swoole_get_function(SW_STRL("test_func")); - std::string b = ", swoole is best"; - auto rs = _func(", swoole is best"); - ASSERT_EQ(rs, test_data + b); - ASSERT_EQ(swoole_get_function(SW_STRL("test_func31")), nullptr); -} - TEST(base, hook) { int count = 0; swoole_add_hook( diff --git a/ext-src/php_swoole_cxx.h b/ext-src/php_swoole_cxx.h index d05bff3aba1..cf1b30e1317 100644 --- a/ext-src/php_swoole_cxx.h +++ b/ext-src/php_swoole_cxx.h @@ -570,25 +570,59 @@ class CharPtr { } }; -struct Callable { - zval zfunc; +class Callable { + private: + zval zfn; zend_fcall_info_cache fcc; + char *fn_name = nullptr; + + Callable() {} + + public: + Callable(zval *_zfn) { + ZVAL_UNDEF(&zfn); + if (!zval_is_true(_zfn)) { + php_swoole_fatal_error(E_WARNING, "illegal callback function"); + return; + } + if (!sw_zend_is_callable_ex(_zfn, nullptr, 0, &fn_name, nullptr, &fcc, nullptr)) { + php_swoole_fatal_error(E_WARNING, "function '%s' is not callable", fn_name); + return; + } + zfn = *_zfn; + zval_add_ref(&zfn); + } + + zend_fcall_info_cache *ptr() { + return &fcc; + } - Callable(zval *_zfunc) { - zfunc = *_zfunc; - Z_TRY_ADDREF_P(&zfunc); + bool ready() { + return !ZVAL_IS_UNDEF(&zfn); } - bool is_callable() { - return zend_is_callable_ex(&zfunc, NULL, 0, NULL, &fcc, NULL); + Callable *dup() { + auto copy = new Callable(); + copy->fcc = fcc; + copy->zfn = zfn; + zval_add_ref(©->zfn); + if (fn_name) { + copy->fn_name = estrdup(fn_name); + } + return copy; } bool call(uint32_t argc, zval *argv, zval *retval) { - return sw_zend_call_function_ex(&zfunc, &fcc, argc, argv, retval) == SUCCESS; + return sw_zend_call_function_ex(&zfn, &fcc, argc, argv, retval) == SUCCESS; } ~Callable() { - Z_TRY_DELREF_P(&zfunc); + if (!ZVAL_IS_UNDEF(&zfn)) { + zval_ptr_dtor(&zfn); + } + if (fn_name) { + efree(fn_name); + } } }; @@ -596,6 +630,10 @@ namespace function { /* must use this API to call event callbacks to ensure that exceptions are handled correctly */ bool call(zend_fcall_info_cache *fci_cache, uint32_t argc, zval *argv, zval *retval, const bool enable_coroutine); Variable call(const std::string &func_name, int argc, zval *argv); + +static inline bool call(Callable *cb, uint32_t argc, zval *argv, zval *retval, const bool enable_coroutine) { + return call(cb->ptr(), argc, argv, retval, enable_coroutine); +} } // namespace function struct Function { @@ -689,7 +727,22 @@ static inline void print_error(zend_object *exception, int severity) { //-----------------------------------namespace end-------------------------------------------- } // namespace zend -static inline zend::Callable *php_swoole_zval_to_callable(zval *zfn, const char *fname, bool allow_null = true) { +/* use void* to match some C callback function pointers */ +static inline void sw_callable_free(void *ptr) { + delete (zend::Callable *) ptr; +} + +static inline zend::Callable *sw_callable_create(zval *zfn) { + auto fn = new zend::Callable(zfn); + if (fn->ready()) { + return fn; + } else { + delete fn; + return nullptr; + } +} + +static inline zend::Callable *sw_callable_create_ex(zval *zfn, const char *fname, bool allow_null = true) { if (zfn == nullptr || ZVAL_IS_NULL(zfn)) { if (!allow_null) { zend_throw_exception_ex( @@ -697,9 +750,8 @@ static inline zend::Callable *php_swoole_zval_to_callable(zval *zfn, const char } return nullptr; } - auto cb = new zend::Callable(zfn); - if (!cb->is_callable()) { - delete cb; + auto cb = sw_callable_create(zfn); + if (!cb) { zend_throw_exception_ex(swoole_exception_ce, SW_ERROR_INVALID_PARAMS, "%s must be of type callable, %s given", @@ -709,8 +761,3 @@ static inline zend::Callable *php_swoole_zval_to_callable(zval *zfn, const char } return cb; } - -static inline void php_swoole_callable_free(void *ptr) { - zend::Callable *cb = (zend::Callable *) ptr; - delete cb; -} diff --git a/ext-src/php_swoole_private.h b/ext-src/php_swoole_private.h index 319b4884dac..a5e2ae3af01 100644 --- a/ext-src/php_swoole_private.h +++ b/ext-src/php_swoole_private.h @@ -972,12 +972,6 @@ static sw_inline void sw_zend_fci_cache_discard(zend_fcall_info_cache *fci_cache } } -/* use void* to match some C callback function pointers */ -static sw_inline void sw_zend_fci_cache_free(void *fci_cache) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) fci_cache); - efree((zend_fcall_info_cache *) fci_cache); -} - #if PHP_VERSION_ID >= 80100 #define sw_php_spl_object_hash(o) php_spl_object_hash(Z_OBJ_P(o)) #else diff --git a/ext-src/php_swoole_server.h b/ext-src/php_swoole_server.h index f96d75305f3..9a75a87c8d8 100644 --- a/ext-src/php_swoole_server.h +++ b/ext-src/php_swoole_server.h @@ -73,9 +73,7 @@ void php_swoole_server_set_port_property(swoole::ListenPort *port, swoole::Serve namespace swoole { struct ServerPortProperty { - zval *callbacks[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; - zend_fcall_info_cache *caches[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; - zval _callbacks[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; + zend::Callable *callbacks[PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM]; Server *serv; ListenPort *port; zval *zsetting; @@ -84,11 +82,11 @@ struct ServerPortProperty { struct ServerProperty { std::vector ports; std::vector user_processes; - zend_fcall_info_cache *callbacks[PHP_SWOOLE_SERVER_CALLBACK_NUM]; - std::unordered_map task_callbacks; + zend::Callable *callbacks[PHP_SWOOLE_SERVER_CALLBACK_NUM]; + std::unordered_map task_callbacks; std::unordered_map task_coroutine_map; std::unordered_map *> send_coroutine_map; - std::vector command_callbacks; + std::vector command_callbacks; }; struct ServerObject { @@ -106,6 +104,14 @@ struct ServerObject { php_swoole_server_get_port_property(serv->get_primary_port())->callbacks[event_type]); } + bool isset_callback(int event_type) { + return property->callbacks[event_type] != nullptr; + } + + zend::Callable *get_callback(int event_type) { + return property->callbacks[event_type]; + } + zend_bool is_websocket_server() { return instanceof_function(get_ce(), swoole_websocket_server_ce); } @@ -132,7 +138,7 @@ void register_admin_server_commands(Server *serv); } // namespace swoole void php_swoole_server_register_callbacks(swServer *serv); -zend_fcall_info_cache *php_swoole_server_get_fci_cache(swServer *serv, int server_fd, int event_type); +zend::Callable *php_swoole_server_get_callback(swServer *serv, int server_fd, int event_type); int php_swoole_create_dir(const char *path, size_t length); void php_swoole_server_before_start(swServer *serv, zval *zobject); bool php_swoole_server_isset_callback(swServer *serv, swListenPort *port, int event_type); diff --git a/ext-src/swoole_client.cc b/ext-src/swoole_client.cc index 8c20c7b4c9a..1f34e4ce8ac 100644 --- a/ext-src/swoole_client.cc +++ b/ext-src/swoole_client.cc @@ -34,19 +34,6 @@ using swoole::String; using swoole::network::Client; using swoole::network::Socket; -struct ClientCallback { - zend_fcall_info_cache cache_onConnect; - zend_fcall_info_cache cache_onReceive; - zend_fcall_info_cache cache_onClose; - zend_fcall_info_cache cache_onError; - zend_fcall_info_cache cache_onBufferFull; - zend_fcall_info_cache cache_onBufferEmpty; -#ifdef SW_USE_OPENSSL - zend_fcall_info_cache cache_onSSLReady; -#endif - zval _object; -}; - static std::unordered_map *> long_connections; zend_class_entry *swoole_client_ce; @@ -58,7 +45,6 @@ static zend_object_handlers swoole_client_exception_handlers; struct ClientObject { Client *cli; zval *zsocket; - ClientCallback *cb; zend_object std; }; @@ -87,14 +73,6 @@ static sw_inline void php_swoole_client_set_zsocket(zval *zobject, zval *zsocket } #endif -static sw_inline ClientCallback *php_swoole_client_get_cb(zval *zobject) { - return php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cb; -} - -static sw_inline void php_swoole_client_set_cb(zval *zobject, ClientCallback *cb) { - php_swoole_client_fetch_object(Z_OBJ_P(zobject))->cb = cb; -} - static void php_swoole_client_free_object(zend_object *object) { zend_object_std_dtor(object); } @@ -352,32 +330,15 @@ bool php_swoole_client_check_setting(Client *cli, zval *zset) { } // length function if (php_swoole_array_get_value(vht, "package_length_func", ztmp)) { - while (1) { - if (Z_TYPE_P(ztmp) == IS_STRING) { - Protocol::LengthFunc func = Protocol::get_function(std::string(Z_STRVAL_P(ztmp), Z_STRLEN_P(ztmp))); - if (func != nullptr) { - cli->protocol.get_package_length = func; - break; - } - } - - char *func_name; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); - return false; - } - efree(func_name); - cli->protocol.get_package_length = php_swoole_length_func; - if (cli->protocol.private_data) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) cli->protocol.private_data); - efree(cli->protocol.private_data); - } - sw_zend_fci_cache_persist(fci_cache); - cli->protocol.private_data = fci_cache; - break; + auto fci_cache = sw_callable_create(ztmp); + if (!fci_cache) { + return false; } - + cli->protocol.get_package_length = php_swoole_length_func; + if (cli->protocol.private_data_1) { + sw_callable_free(cli->protocol.private_data_1); + } + cli->protocol.private_data_1 = fci_cache; cli->protocol.package_length_size = 0; cli->protocol.package_length_type = '\0'; cli->protocol.package_length_offset = SW_IPC_BUFFER_SIZE; @@ -526,10 +487,9 @@ static void php_swoole_client_free(zval *zobject, Client *cli) { swoole_timer_del(cli->timer); cli->timer = nullptr; } - if (cli->protocol.private_data) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) cli->protocol.private_data); - efree(cli->protocol.private_data); - cli->protocol.private_data = nullptr; + if (cli->protocol.private_data_1) { + sw_callable_free(cli->protocol.private_data_1); + cli->protocol.private_data_1 = nullptr; } // long tcp connection, delete from php_sw_long_connections if (cli->keep) { @@ -558,14 +518,14 @@ static void php_swoole_client_free(zval *zobject, Client *cli) { } ssize_t php_swoole_length_func(const Protocol *protocol, Socket *_socket, PacketLength *pl) { - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) protocol->private_data; + zend::Callable *cb = (zend::Callable *) protocol->private_data_1; zval zdata; zval retval; ssize_t ret = -1; // TODO: reduce memory copy ZVAL_STRINGL(&zdata, pl->buf, pl->buf_size); - if (UNEXPECTED(sw_zend_call_function_ex2(nullptr, fci_cache, 1, &zdata, &retval) != SUCCESS)) { + if (UNEXPECTED(sw_zend_call_function_ex2(nullptr, cb->ptr(), 1, &zdata, &retval) != SUCCESS)) { php_swoole_fatal_error(E_WARNING, "length function handler error"); } else { ret = zval_get_long(&retval); @@ -685,7 +645,6 @@ static PHP_METHOD(swoole_client, __construct) { } // init php_swoole_client_set_cli(ZEND_THIS, nullptr); - php_swoole_client_set_cb(ZEND_THIS, nullptr); #ifdef SWOOLE_SOCKETS_SUPPORT php_swoole_client_set_zsocket(ZEND_THIS, nullptr); #endif @@ -700,12 +659,6 @@ static PHP_METHOD(swoole_client, __destruct) { if (cli) { sw_zend_call_method_with_0_params(ZEND_THIS, swoole_client_ce, nullptr, "close", nullptr); } - // free memory - ClientCallback *cb = php_swoole_client_get_cb(ZEND_THIS); - if (cb) { - efree(cb); - php_swoole_client_set_cb(ZEND_THIS, nullptr); - } } static PHP_METHOD(swoole_client, set) { diff --git a/ext-src/swoole_client_coro.cc b/ext-src/swoole_client_coro.cc index 56b0115d978..4db4778e1ff 100644 --- a/ext-src/swoole_client_coro.cc +++ b/ext-src/swoole_client_coro.cc @@ -131,10 +131,9 @@ static zend_object *client_coro_create_object(zend_class_entry *ce) { } static void client_coro_socket_dtor(ClientCoroObject *client) { - if (client->socket->protocol.private_data) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) client->socket->protocol.private_data); - efree(client->socket->protocol.private_data); - client->socket->protocol.private_data = nullptr; + if (client->socket->protocol.private_data_1) { + sw_callable_free(client->socket->protocol.private_data_1); + client->socket->protocol.private_data_1 = nullptr; } client->socket = nullptr; zend_update_property_null(Z_OBJCE_P(&client->zobject), SW_Z8_OBJ_P(&client->zobject), ZEND_STRL("socket")); diff --git a/ext-src/swoole_coroutine_scheduler.cc b/ext-src/swoole_coroutine_scheduler.cc index 5b4a530f672..ad20b1e65e0 100644 --- a/ext-src/swoole_coroutine_scheduler.cc +++ b/ext-src/swoole_coroutine_scheduler.cc @@ -106,16 +106,15 @@ void php_swoole_coroutine_scheduler_minit(int module_number) { swoole_coroutine_scheduler_ce->ce_flags |= ZEND_ACC_FINAL; } -static zend_fcall_info_cache exit_condition_fci_cache; -static bool exit_condition_cleaner; +static zend::Callable *exit_condition_fci_cache = nullptr; static bool php_swoole_coroutine_reactor_can_exit(Reactor *reactor, size_t &event_num) { zval retval; int success; - SW_ASSERT(exit_condition_fci_cache.function_handler); + SW_ASSERT(exit_condition_fci_cache); ZVAL_NULL(&retval); - success = sw_zend_call_function_ex(nullptr, &exit_condition_fci_cache, 0, nullptr, &retval); + success = sw_zend_call_function_ex(nullptr, exit_condition_fci_cache->ptr(), 0, nullptr, &retval); if (UNEXPECTED(success != SUCCESS)) { php_swoole_fatal_error(E_ERROR, "Coroutine can_exit callback handler error"); } @@ -135,6 +134,11 @@ void php_swoole_coroutine_scheduler_rshutdown() { return SW_TRAVERSE_KEEP; } }); + + if (exit_condition_fci_cache) { + sw_callable_free(exit_condition_fci_cache); + exit_condition_fci_cache = nullptr; + } } void php_swoole_set_coroutine_option(zend_array *vht) { @@ -194,33 +198,16 @@ PHP_METHOD(swoole_coroutine_scheduler, set) { } /* Reactor can exit */ if ((ztmp = zend_hash_str_find(vht, ZEND_STRL("exit_condition")))) { - char *func_name; - if (exit_condition_fci_cache.function_handler) { - sw_zend_fci_cache_discard(&exit_condition_fci_cache); - exit_condition_fci_cache.function_handler = nullptr; + if (exit_condition_fci_cache) { + sw_callable_free(exit_condition_fci_cache); } - if (!ZVAL_IS_NULL(ztmp)) { - if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, &exit_condition_fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "exit_condition '%s' is not callable", func_name); - } else { - efree(func_name); - sw_zend_fci_cache_persist(&exit_condition_fci_cache); - if (!exit_condition_cleaner) { - php_swoole_register_rshutdown_callback( - [](void *data) { - if (exit_condition_fci_cache.function_handler) { - sw_zend_fci_cache_discard(&exit_condition_fci_cache); - exit_condition_fci_cache.function_handler = nullptr; - } - }, - nullptr); - exit_condition_cleaner = true; - } - SwooleG.user_exit_condition = php_swoole_coroutine_reactor_can_exit; - if (sw_reactor()) { - sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_USER_AFTER_DEFAULT, - SwooleG.user_exit_condition); - } + + exit_condition_fci_cache = sw_callable_create(ztmp); + if (exit_condition_fci_cache) { + SwooleG.user_exit_condition = php_swoole_coroutine_reactor_can_exit; + if (sw_reactor()) { + sw_reactor()->set_exit_condition(Reactor::EXIT_CONDITION_USER_AFTER_DEFAULT, + SwooleG.user_exit_condition); } } else { if (sw_reactor()) { diff --git a/ext-src/swoole_event.cc b/ext-src/swoole_event.cc index 5fa07365cc9..e5960ccccc3 100644 --- a/ext-src/swoole_event.cc +++ b/ext-src/swoole_event.cc @@ -138,7 +138,7 @@ static int event_readable_callback(Reactor *reactor, Event *event) { zval argv[1]; argv[0] = peo->zsocket; - auto *fcc = &peo->readable_callback->fcc; + auto fcc = peo->readable_callback->ptr(); if (UNEXPECTED(!zend::function::call(fcc, 1, argv, nullptr, php_swoole_is_enable_coroutine()))) { php_swoole_fatal_error(E_WARNING, @@ -159,7 +159,7 @@ static int event_writable_callback(Reactor *reactor, Event *event) { zval argv[1]; argv[0] = peo->zsocket; - auto *fcc = &peo->writable_callback->fcc; + auto fcc = peo->writable_callback->ptr(); if (UNEXPECTED(!zend::function::call(fcc, 1, argv, nullptr, php_swoole_is_enable_coroutine()))) { php_swoole_fatal_error(E_WARNING, @@ -201,16 +201,16 @@ static int event_error_callback(Reactor *reactor, Event *event) { } static void event_defer_callback(void *data) { - zend::Callable *fn = (zend::Callable *) data; - if (UNEXPECTED(!zend::function::call(&fn->fcc, 0, nullptr, nullptr, php_swoole_is_enable_coroutine()))) { + zend::Callable *cb = (zend::Callable *) data; + if (UNEXPECTED(!zend::function::call(cb, 0, nullptr, nullptr, php_swoole_is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s::defer callback handler error", ZSTR_VAL(swoole_event_ce->name)); } - delete fn; + delete cb; } static void event_end_callback(void *data) { zend::Callable *cb = (zend::Callable *) data; - if (UNEXPECTED(!zend::function::call(&cb->fcc, 0, nullptr, nullptr, php_swoole_is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, 0, nullptr, nullptr, php_swoole_is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s::end callback handler error", ZSTR_VAL(swoole_event_ce->name)); } } @@ -434,14 +434,14 @@ static PHP_FUNCTION(swoole_event_add) { RETURN_FALSE; } - auto readable_callback = php_swoole_zval_to_callable(zreadable_callback, "readable_callback"); + auto readable_callback = sw_callable_create_ex(zreadable_callback, "readable_callback", true); if ((events & SW_EVENT_READ) && readable_callback == nullptr) { php_swoole_fatal_error( E_WARNING, "%s: unable to find readable callback of fd [%d]", ZSTR_VAL(swoole_event_ce->name), socket_fd); RETURN_FALSE; } - auto writable_callback = php_swoole_zval_to_callable(zwritable_callback, "writable_callback"); + auto writable_callback = sw_callable_create_ex(zwritable_callback, "writable_callback", true); if ((events & SW_EVENT_WRITE) && writable_callback == nullptr) { php_swoole_fatal_error( E_WARNING, "%s: unable to find writable callback of fd [%d]", ZSTR_VAL(swoole_event_ce->name), socket_fd); @@ -539,17 +539,17 @@ static PHP_FUNCTION(swoole_event_set) { } EventObject *peo = (EventObject *) socket->object; - auto readable_callback = php_swoole_zval_to_callable(zreadable_callback, "readable_callback"); - auto writable_callback = php_swoole_zval_to_callable(zwritable_callback, "writable_callback"); + auto readable_callback = sw_callable_create_ex(zreadable_callback, "readable_callback"); + auto writable_callback = sw_callable_create_ex(zwritable_callback, "writable_callback"); if (readable_callback) { if (peo->readable_callback) { - swoole_event_defer(php_swoole_callable_free, peo->readable_callback); + swoole_event_defer(sw_callable_free, peo->readable_callback); } peo->readable_callback = readable_callback; } if (writable_callback) { if (peo->writable_callback) { - swoole_event_defer(php_swoole_callable_free, peo->writable_callback); + swoole_event_defer(sw_callable_free, peo->writable_callback); } peo->writable_callback = writable_callback; } @@ -609,7 +609,7 @@ static PHP_FUNCTION(swoole_event_defer) { ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); php_swoole_check_reactor(); - auto fn = php_swoole_zval_to_callable(zfn, "fn"); + auto fn = sw_callable_create(zfn); swoole_event_defer(event_defer_callback, fn); RETURN_TRUE; @@ -627,29 +627,28 @@ static PHP_FUNCTION(swoole_event_cycle) { event_check_reactor(); - auto callback = php_swoole_zval_to_callable(zcallback, "callback"); - - if (callback == nullptr) { + if (ZVAL_IS_NULL(zcallback)) { if (sw_reactor()->idle_task.callback == nullptr) { RETURN_FALSE; } else { - swoole_event_defer(php_swoole_callable_free, sw_reactor()->idle_task.data); + swoole_event_defer(sw_callable_free, sw_reactor()->idle_task.data); sw_reactor()->idle_task.callback = nullptr; sw_reactor()->idle_task.data = nullptr; RETURN_TRUE; } } + auto callback = sw_callable_create(zcallback); if (!before) { if (sw_reactor()->idle_task.data != nullptr) { - swoole_event_defer(php_swoole_callable_free, sw_reactor()->idle_task.data); + swoole_event_defer(sw_callable_free, sw_reactor()->idle_task.data); } sw_reactor()->idle_task.callback = event_end_callback; sw_reactor()->idle_task.data = callback; } else { if (sw_reactor()->future_task.data != nullptr) { - swoole_event_defer(php_swoole_callable_free, sw_reactor()->future_task.data); + swoole_event_defer(sw_callable_free, sw_reactor()->future_task.data); } sw_reactor()->future_task.callback = event_end_callback; diff --git a/ext-src/swoole_http2_server.cc b/ext-src/swoole_http2_server.cc index f6eebfd6569..fbf71487584 100644 --- a/ext-src/swoole_http2_server.cc +++ b/ext-src/swoole_http2_server.cc @@ -246,8 +246,8 @@ static void http2_server_onRequest(Http2Session *client, Http2Stream *stream) { zval *zserver = ctx->request.zserver; Server *serv = (Server *) ctx->private_data; zval args[2]; - zend_fcall_info_cache *fci_cache = nullptr; Connection *serv_sock = nullptr; + zend::Callable *cb = nullptr; int server_fd = 0; Connection *conn = serv->get_connection_by_session_id(ctx->fd); @@ -274,8 +274,8 @@ static void http2_server_onRequest(Http2Session *client, Http2Stream *stream) { add_assoc_long(zserver, "master_time", conn->last_recv_time); add_assoc_string(zserver, "server_protocol", (char *) "HTTP/2"); - fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onRequest); - ctx->private_data_2 = fci_cache; + cb = php_swoole_server_get_callback(serv, server_fd, SW_SERVER_CB_onRequest); + ctx->private_data_2 = cb; if (ctx->onBeforeRequest && !ctx->onBeforeRequest(ctx)) { return; @@ -283,7 +283,7 @@ static void http2_server_onRequest(Http2Session *client, Http2Stream *stream) { args[0] = *ctx->request.zobject; args[1] = *ctx->response.zobject; - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, serv->is_enable_coroutine()))) { stream->reset(SW_HTTP2_ERROR_INTERNAL_ERROR); php_swoole_error(E_WARNING, "%s->onRequest[v2] handler error", ZSTR_VAL(swoole_http_server_ce->name)); } diff --git a/ext-src/swoole_http_client_coro.cc b/ext-src/swoole_http_client_coro.cc index 6aecc76546a..7f3d88eadec 100644 --- a/ext-src/swoole_http_client_coro.cc +++ b/ext-src/swoole_http_client_coro.cc @@ -740,7 +740,7 @@ void Client::apply_setting(zval *zset, const bool check_all) { if (write_func) { delete write_func; } - write_func = php_swoole_zval_to_callable(ztmp, "write_func"); + write_func = sw_callable_create(ztmp); } } if (socket) { diff --git a/ext-src/swoole_http_server.cc b/ext-src/swoole_http_server.cc index b94b7a095ee..58c75327075 100644 --- a/ext-src/swoole_http_server.cc +++ b/ext-src/swoole_http_server.cc @@ -39,11 +39,11 @@ static bool http_context_send_data(HttpContext *ctx, const char *data, size_t le static bool http_context_sendfile(HttpContext *ctx, const char *file, uint32_t l_file, off_t offset, size_t length); static bool http_context_disconnect(HttpContext *ctx); -static void http_server_process_request(Server *serv, zend_fcall_info_cache *fci_cache, HttpContext *ctx) { +static void http_server_process_request(Server *serv, zend::Callable *cb, HttpContext *ctx) { zval args[2]; args[0] = *ctx->request.zobject; args[1] = *ctx->response.zobject; - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onRequest handler error", ZSTR_VAL(swoole_http_server_ce->name)); #ifdef SW_HTTP_SERVICE_UNAVAILABLE_PACKET ctx->send(ctx, SW_STRL(SW_HTTP_SERVICE_UNAVAILABLE_PACKET)); @@ -147,11 +147,11 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { // begin to check and call registerd callback do { - zend_fcall_info_cache *fci_cache = nullptr; + zend::Callable *cb = nullptr; if (conn->websocket_status == WebSocket::STATUS_CONNECTION) { - fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onHandshake); - if (fci_cache == nullptr) { + cb = php_swoole_server_get_callback(serv, server_fd, SW_SERVER_CB_onHandshake); + if (cb == nullptr) { swoole_websocket_onHandshake(serv, port, ctx); goto _dtor_and_return; } else { @@ -159,17 +159,17 @@ int php_swoole_http_server_onReceive(Server *serv, RecvData *req) { ctx->upgrade = 1; } } else { - fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onRequest); - if (fci_cache == nullptr) { + cb = php_swoole_server_get_callback(serv, server_fd, SW_SERVER_CB_onRequest); + if (cb == nullptr) { swoole_websocket_onRequest(ctx); goto _dtor_and_return; } } - ctx->private_data_2 = fci_cache; + ctx->private_data_2 = cb; if (ctx->onBeforeRequest && !ctx->onBeforeRequest(ctx)) { return SW_OK; } - http_server_process_request(serv, fci_cache, ctx); + http_server_process_request(serv, cb, ctx); } while (0); _dtor_and_return: @@ -423,9 +423,9 @@ void swoole_http_server_onAfterResponse(HttpContext *ctx) { [](void *private_data) { HttpContext *ctx = (HttpContext *) private_data; Server *serv = (Server *) ctx->private_data; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ctx->private_data_2; + zend::Callable *cb = (zend::Callable *) ctx->private_data_2; swoole_trace("[POP 2] ctx=%p, request=%p", ctx, ctx->request.zobject); - http_server_process_request(serv, fci_cache, ctx); + http_server_process_request(serv, cb, ctx); zval_ptr_dtor(ctx->request.zobject); zval_ptr_dtor(ctx->response.zobject); }, diff --git a/ext-src/swoole_http_server_coro.cc b/ext-src/swoole_http_server_coro.cc index a03c53d6681..b4b4b71edc5 100644 --- a/ext-src/swoole_http_server_coro.cc +++ b/ext-src/swoole_http_server_coro.cc @@ -54,9 +54,8 @@ namespace coroutine { class HttpServer { public: Socket *socket; - zend_fcall_info_cache *default_handler; - std::unordered_map handlers; - zval zcallbacks; + zend::Callable *default_handler; + std::unordered_map handlers; bool running; zval zclients; @@ -80,7 +79,6 @@ class HttpServer { HttpServer(enum swSocketType type) { socket = new Socket(type); default_handler = nullptr; - array_init(&zcallbacks); array_init(&zclients); running = true; @@ -100,27 +98,28 @@ class HttpServer { ~HttpServer() { sw_free(upload_tmp_dir); - zval_ptr_dtor(&zcallbacks); zval_ptr_dtor(&zclients); + for (auto i = handlers.begin(); i != handlers.end(); i++) { + sw_callable_free(i->second); + } delete socket; } - void set_handler(std::string pattern, zval *zcallback, const zend_fcall_info_cache *fci_cache) { - handlers[pattern] = *fci_cache; + void set_handler(std::string pattern, zend::Callable *cb) { + handlers[pattern] = cb; if (pattern == "/") { - default_handler = &handlers[pattern]; + default_handler = cb; } - zend::array_set(&zcallbacks, pattern.c_str(), pattern.length(), zcallback); } - zend_fcall_info_cache *get_handler(HttpContext *ctx) { + zend::Callable *get_handler(HttpContext *ctx) { for (auto i = handlers.begin(); i != handlers.end(); i++) { - if (&i->second == default_handler) { + if (i->second == default_handler) { continue; } if (swoole_str_istarts_with( ctx->request.path, ctx->request.path_len, i->first.c_str(), i->first.length())) { - return &i->second; + return i->second; } } return default_handler; @@ -302,12 +301,6 @@ void php_swoole_http_server_coro_minit(int module_number) { HttpServerObject, std); swoole_http_server_coro_ce->ce_flags |= ZEND_ACC_FINAL; - swoole_http_server_coro_handlers.get_gc = [](sw_zend7_object *object, zval **gc_data, int *gc_count) { - HttpServerObject *hs = php_swoole_http_server_coro_fetch_object(SW_Z7_OBJ_P(object)); - *gc_data = &hs->server->zcallbacks; - *gc_count = 1; - return zend_std_get_properties(object); - }; zend_declare_property_long(swoole_http_server_coro_ce, ZEND_STRL("fd"), -1, ZEND_ACC_PUBLIC); zend_declare_property_null(swoole_http_server_coro_ce, ZEND_STRL("host"), ZEND_ACC_PUBLIC); @@ -386,18 +379,22 @@ static PHP_METHOD(swoole_http_server_coro, __construct) { static PHP_METHOD(swoole_http_server_coro, handle) { char *pattern; size_t pattern_len; + zval *zfn; HttpServer *hs = http_server_get_object(Z_OBJ_P(ZEND_THIS)); - zend_fcall_info fci; - zend_fcall_info_cache fci_cache; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STRING(pattern, pattern_len) - Z_PARAM_FUNC(fci, fci_cache) + Z_PARAM_ZVAL(zfn) ZEND_PARSE_PARAMETERS_END(); + auto cb = sw_callable_create(zfn); + if (!cb) { + RETURN_FALSE; + } + std::string key(pattern, pattern_len); - hs->set_handler(key, ZEND_CALL_ARG(execute_data, 2), &fci_cache); + hs->set_handler(key, cb); } static PHP_METHOD(swoole_http_server_coro, set) { @@ -665,13 +662,13 @@ static PHP_METHOD(swoole_http_server_coro, onAccept) { http_server_add_server_array(Z_ARRVAL_P(zserver), SW_ZSTR_KNOWN(SW_ZEND_STR_REMOTE_ADDR), remote_addr.ptr()); remote_addr.add_ref(); - zend_fcall_info_cache *fci_cache = hs->get_handler(ctx); + zend::Callable *cb = hs->get_handler(ctx); zval args[2] = {*ctx->request.zobject, *ctx->response.zobject}; bool keep_alive = swoole_http_should_keep_alive(&ctx->parser) && !ctx->websocket; sock->get_socket()->recv_wait = 0; - if (fci_cache) { - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, 0))) { + if (cb) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, 0))) { php_swoole_error(E_WARNING, "handler error"); } } else { @@ -731,11 +728,11 @@ static void http2_server_onRequest(Http2Session *session, Http2Stream *stream) { add_assoc_string(zserver, "remote_addr", (char *) sock->get_ip()); add_assoc_string(zserver, "server_protocol", (char *) "HTTP/2"); - zend_fcall_info_cache *fci_cache = hs->get_handler(ctx); + zend::Callable *cb = hs->get_handler(ctx); zval args[2] = {*ctx->request.zobject, *ctx->response.zobject}; - if (fci_cache) { - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, true))) { + if (cb) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, true))) { stream->reset(SW_HTTP2_ERROR_INTERNAL_ERROR); php_swoole_error(E_WARNING, "%s->onRequest[v2] handler error", ZSTR_VAL(swoole_http_server_ce->name)); } diff --git a/ext-src/swoole_process.cc b/ext-src/swoole_process.cc index 3cce2a1dd55..c2f87b8beb0 100644 --- a/ext-src/swoole_process.cc +++ b/ext-src/swoole_process.cc @@ -35,7 +35,7 @@ static zend_object_handlers swoole_process_handlers; static uint32_t round_process_id = 0; static thread_local uint32_t server_user_worker_id = 0; -static zend_fcall_info_cache *signal_fci_caches[SW_SIGNO_MAX] = {}; +static zend::Callable *signal_fci_caches[SW_SIGNO_MAX] = {}; struct ProcessObject { Worker *worker; @@ -449,7 +449,7 @@ static PHP_METHOD(swoole_process, signal) { SW_MUST_BE_MAIN_THREAD(); zend_long signo = 0; zval *zcallback = nullptr; - zend_fcall_info_cache *fci_cache = nullptr; + zend::Callable *fci_cache = nullptr; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_LONG(signo) @@ -483,7 +483,7 @@ static PHP_METHOD(swoole_process, signal) { swoole_signal_set(signo, nullptr); #endif signal_fci_caches[signo] = nullptr; - swoole_event_defer(sw_zend_fci_cache_free, fci_cache); + swoole_event_defer(sw_callable_free, fci_cache); SwooleTG.signal_listener_num--; RETURN_TRUE; } else { @@ -493,22 +493,16 @@ static PHP_METHOD(swoole_process, signal) { } else if (Z_TYPE_P(zcallback) == IS_LONG && Z_LVAL_P(zcallback) == (zend_long) SIG_IGN) { handler = nullptr; } else { - char *func_name; - fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(zcallback, nullptr, 0, &func_name, 0, fci_cache, nullptr)) { - php_swoole_error(E_WARNING, "function '%s' is not callable", func_name); - efree(func_name); - efree(fci_cache); + fci_cache = sw_callable_create(zcallback); + if (!fci_cache) { RETURN_FALSE; } - efree(func_name); - sw_zend_fci_cache_persist(fci_cache); handler = php_swoole_onSignal; } if (sw_server() && sw_server()->is_sync_process()) { if (signal_fci_caches[signo]) { - sw_zend_fci_cache_free(signal_fci_caches[signo]); + sw_callable_free(signal_fci_caches[signo]); } else { SwooleTG.signal_listener_num++; } @@ -531,7 +525,7 @@ static PHP_METHOD(swoole_process, signal) { if (signal_fci_caches[signo]) { // free the old fci_cache - swoole_event_defer(sw_zend_fci_cache_free, signal_fci_caches[signo]); + swoole_event_defer(sw_callable_free, signal_fci_caches[signo]); } else { SwooleTG.signal_listener_num++; } @@ -594,13 +588,13 @@ static PHP_METHOD(swoole_process, alarm) { * safe signal */ static void php_swoole_onSignal(int signo) { - zend_fcall_info_cache *fci_cache = signal_fci_caches[signo]; + auto fci_cache = signal_fci_caches[signo]; if (fci_cache) { zval argv[1]; ZVAL_LONG(&argv[0], signo); - if (UNEXPECTED(!zend::function::call(fci_cache, 1, argv, nullptr, php_swoole_is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(fci_cache->ptr(), 1, argv, nullptr, php_swoole_is_enable_coroutine()))) { php_swoole_fatal_error( E_WARNING, "%s: signal [%d] handler error", ZSTR_VAL(swoole_process_ce->name), signo); } @@ -617,10 +611,9 @@ zend_bool php_swoole_signal_isset_handler(int signo) { void php_swoole_process_clean() { for (int i = 0; i < SW_SIGNO_MAX; i++) { - zend_fcall_info_cache *fci_cache = signal_fci_caches[i]; + auto fci_cache = signal_fci_caches[i]; if (fci_cache) { - sw_zend_fci_cache_discard(fci_cache); - efree(fci_cache); + sw_callable_free(fci_cache); signal_fci_caches[i] = nullptr; } } @@ -637,10 +630,8 @@ void php_swoole_process_rshutdown() { int php_swoole_process_start(Worker *process, zval *zobject) { zval *zcallback = sw_zend_read_property_ex(swoole_process_ce, zobject, SW_ZSTR_KNOWN(SW_ZEND_STR_CALLBACK), 0); - zend_fcall_info_cache fci_cache; - - if (!sw_zend_is_callable_ex(zcallback, nullptr, 0, nullptr, 0, &fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "Illegal callback function of %s", SW_Z_OBJCE_NAME_VAL_P(zobject)); + auto fci_cache = sw_callable_create(zcallback); + if (!fci_cache) { return SW_ERR; } @@ -681,13 +672,14 @@ int php_swoole_process_start(Worker *process, zval *zobject) { return SW_ERR; } // main function - if (UNEXPECTED(!zend::function::call(&fci_cache, 1, zobject, nullptr, proc->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(fci_cache->ptr(), 1, zobject, nullptr, proc->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onStart handler error", SW_Z_OBJCE_NAME_VAL_P(zobject)); } // eventloop start if (proc->enable_coroutine) { php_swoole_event_wait(); } + sw_callable_free(fci_cache); // equivalent to exit zend_bailout(); diff --git a/ext-src/swoole_process_pool.cc b/ext-src/swoole_process_pool.cc index b7065bf8427..f3c0e444c1d 100644 --- a/ext-src/swoole_process_pool.cc +++ b/ext-src/swoole_process_pool.cc @@ -33,10 +33,10 @@ static Worker *current_worker = nullptr; struct ProcessPoolObject { ProcessPool *pool; - zend_fcall_info_cache *onStart; - zend_fcall_info_cache *onWorkerStart; - zend_fcall_info_cache *onWorkerStop; - zend_fcall_info_cache *onMessage; + zend::Callable *onStart; + zend::Callable *onWorkerStart; + zend::Callable *onWorkerStop; + zend::Callable *onMessage; zend_bool enable_coroutine; zend_bool enable_message_bus; zend_object std; @@ -75,20 +75,16 @@ static void process_pool_free_object(zend_object *object) { } if (pp->onWorkerStart) { - sw_zend_fci_cache_discard(pp->onWorkerStart); - efree(pp->onWorkerStart); + sw_callable_free(pp->onWorkerStart); } if (pp->onMessage) { - sw_zend_fci_cache_discard(pp->onMessage); - efree(pp->onMessage); + sw_callable_free(pp->onMessage); } if (pp->onWorkerStop) { - sw_zend_fci_cache_discard(pp->onWorkerStop); - efree(pp->onWorkerStop); + sw_callable_free(pp->onWorkerStop); } if (pp->onStart) { - sw_zend_fci_cache_discard(pp->onStart); - efree(pp->onStart); + sw_callable_free(pp->onStart); } zend_object_std_dtor(object); @@ -167,7 +163,7 @@ static void process_pool_onWorkerStart(ProcessPool *pool, Worker *worker) { zval args[2]; args[0] = *zobject; ZVAL_LONG(&args[1], worker->id); - if (UNEXPECTED(!zend::function::call(pp->onWorkerStart, 2, args, nullptr, pp->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(pp->onWorkerStart->ptr(), 2, args, nullptr, pp->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onWorkerStart handler error", SW_Z_OBJCE_NAME_VAL_P(zobject)); } } @@ -192,7 +188,7 @@ static void process_pool_onMessage(ProcessPool *pool, RecvData *msg) { } auto *worker = sw_worker(); worker->set_status_to_busy(); - if (UNEXPECTED(!zend::function::call(pp->onMessage, 2, args, nullptr, pp->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(pp->onMessage->ptr(), 2, args, nullptr, pp->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onMessage handler error", SW_Z_OBJCE_NAME_VAL_P(zobject)); } worker->add_request_count(); @@ -212,7 +208,7 @@ static void process_pool_onWorkerStop(ProcessPool *pool, Worker *worker) { args[0] = *zobject; ZVAL_LONG(&args[1], worker->id); - if (UNEXPECTED(!zend::function::call(pp->onWorkerStop, 2, args, nullptr, false))) { + if (UNEXPECTED(!zend::function::call(pp->onWorkerStop->ptr(), 2, args, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onWorkerStop handler error", SW_Z_OBJCE_NAME_VAL_P(zobject)); } } @@ -324,9 +320,7 @@ static PHP_METHOD(swoole_process_pool, set) { static PHP_METHOD(swoole_process_pool, on) { char *name; size_t l_name; - - zend_fcall_info fci; - zend_fcall_info_cache fci_cache; + zval *zfn; ProcessPool *pool = process_pool_get_and_check_pool(ZEND_THIS); @@ -337,59 +331,40 @@ static PHP_METHOD(swoole_process_pool, on) { ZEND_PARSE_PARAMETERS_START_EX(ZEND_PARSE_PARAMS_THROW, 2, 2) Z_PARAM_STRING(name, l_name) - Z_PARAM_FUNC(fci, fci_cache); + Z_PARAM_ZVAL(zfn); ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); ProcessPoolObject *pp = process_pool_fetch_object(ZEND_THIS); if (SW_STRCASEEQ(name, l_name, "WorkerStart")) { if (pp->onWorkerStart) { - sw_zend_fci_cache_discard(pp->onWorkerStart); - efree(pp->onWorkerStart); - } else { - pp->onWorkerStart = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); + sw_callable_free(pp->onWorkerStart); } - *pp->onWorkerStart = fci_cache; - sw_zend_fci_cache_persist(pp->onWorkerStart); - RETURN_TRUE; + pp->onWorkerStart = sw_callable_create(zfn); } else if (SW_STRCASEEQ(name, l_name, "Message")) { if (pool->ipc_mode == SW_IPC_NONE) { php_swoole_fatal_error(E_WARNING, "cannot set onMessage event with ipc_type=0"); RETURN_FALSE; } if (pp->onMessage) { - sw_zend_fci_cache_discard(pp->onMessage); - efree(pp->onMessage); - } else { - pp->onMessage = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); + sw_callable_free(pp->onMessage); } - *pp->onMessage = fci_cache; - sw_zend_fci_cache_persist(pp->onMessage); - RETURN_TRUE; + pp->onMessage = sw_callable_create(zfn); } else if (SW_STRCASEEQ(name, l_name, "WorkerStop")) { if (pp->onWorkerStop) { - sw_zend_fci_cache_discard(pp->onWorkerStop); - efree(pp->onWorkerStop); - } else { - pp->onWorkerStop = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); + sw_callable_free(pp->onWorkerStop); } - *pp->onWorkerStop = fci_cache; - sw_zend_fci_cache_persist(pp->onWorkerStop); - RETURN_TRUE; + pp->onWorkerStop = sw_callable_create(zfn); } else if (SW_STRCASEEQ(name, l_name, "Start")) { if (pp->onStart) { - sw_zend_fci_cache_discard(pp->onStart); - efree(pp->onStart); - } else { - pp->onStart = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); + sw_callable_free(pp->onStart); } - *pp->onStart = fci_cache; - sw_zend_fci_cache_persist(pp->onStart); - RETURN_TRUE; + pp->onStart = sw_callable_create(zfn); } else { php_swoole_error(E_WARNING, "unknown event type[%s]", name); RETURN_FALSE; } + RETURN_TRUE; } static PHP_METHOD(swoole_process_pool, listen) { @@ -534,7 +509,7 @@ static PHP_METHOD(swoole_process_pool, start) { if (pp->onStart) { zval args[1]; args[0] = *ZEND_THIS; - if (UNEXPECTED(!zend::function::call(pp->onStart, 1, args, nullptr, 0))) { + if (UNEXPECTED(!zend::function::call(pp->onStart->ptr(), 1, args, nullptr, 0))) { php_swoole_error(E_WARNING, "%s->onStart handler error", SW_Z_OBJCE_NAME_VAL_P(ZEND_THIS)); } } diff --git a/ext-src/swoole_redis_server.cc b/ext-src/swoole_redis_server.cc index 3d0cb232f0b..14270d177e9 100644 --- a/ext-src/swoole_redis_server.cc +++ b/ext-src/swoole_redis_server.cc @@ -35,7 +35,7 @@ namespace Redis = swoole::redis; zend_class_entry *swoole_redis_server_ce; zend_object_handlers swoole_redis_server_handlers; -static SW_THREAD_LOCAL std::unordered_map redis_handlers; +static SW_THREAD_LOCAL std::unordered_map redis_handlers; SW_EXTERN_C_BEGIN static PHP_METHOD(swoole_redis_server, setHandler); @@ -71,7 +71,7 @@ void php_swoole_redis_server_minit(int module_number) { void php_swoole_redis_server_rshutdown() { for (auto i = redis_handlers.begin(); i != redis_handlers.end(); i++) { - sw_zend_fci_cache_discard(&i->second); + sw_callable_free(i->second); } redis_handlers.clear(); } @@ -169,14 +169,14 @@ int php_swoole_redis_server_onReceive(Server *serv, RecvData *req) { return serv->send(fd, err_msg, length) ? SW_OK : SW_ERR; } - zend_fcall_info_cache *fci_cache = &i->second; + auto fci_cache = i->second; zval args[2]; zval retval; ZVAL_LONG(&args[0], fd); args[1] = zparams; - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, &retval, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(fci_cache->ptr(), 2, args, &retval, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onRequest with command '%.*s' handler error", ZSTR_VAL(swoole_redis_server_ce->name), @@ -209,13 +209,10 @@ static PHP_METHOD(swoole_redis_server, setHandler) { RETURN_FALSE; } - char *func_name; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(zcallback, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); + auto fci_cache = sw_callable_create(zcallback); + if (!fci_cache) { return; } - efree(func_name); char _command[SW_REDIS_MAX_COMMAND_SIZE]; size_t _command_len = sw_snprintf(_command, sizeof(_command), "_handler_%s", command); @@ -230,11 +227,10 @@ static PHP_METHOD(swoole_redis_server, setHandler) { std::string key(_command, _command_len); auto i = redis_handlers.find(key); if (i != redis_handlers.end()) { - sw_zend_fci_cache_discard(&i->second); + sw_callable_free(i->second); } - sw_zend_fci_cache_persist(fci_cache); - redis_handlers[key] = *fci_cache; + redis_handlers[key] = fci_cache; RETURN_TRUE; } diff --git a/ext-src/swoole_runtime.cc b/ext-src/swoole_runtime.cc index 17fea258a6e..8b4afcda7b0 100644 --- a/ext-src/swoole_runtime.cc +++ b/ext-src/swoole_runtime.cc @@ -234,7 +234,7 @@ struct real_func { zend_internal_arg_info *ori_arg_info; uint32_t ori_fn_flags; uint32_t ori_num_args; - zend_fcall_info_cache *fci_cache; + zend::Callable *fci_cache; zval name; }; @@ -262,7 +262,7 @@ void php_swoole_runtime_rshutdown() { */ if (rf->fci_cache) { zval_dtor(&rf->name); - efree(rf->fci_cache); + sw_callable_free(rf->fci_cache); } rf->function->internal_function.handler = rf->ori_handler; rf->function->internal_function.arg_info = rf->ori_arg_info; @@ -2000,15 +2000,11 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend memcpy(func + 7, fn_str->val, fn_str->len); ZVAL_STRINGL(&rf->name, func, fn_str->len + 7); - - char *func_name; - zend_fcall_info_cache *func_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(&rf->name, nullptr, 0, &func_name, nullptr, func_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); + auto fci_cache = sw_callable_create(&rf->name); + if (!fci_cache) { return; } - efree(func_name); - rf->fci_cache = func_cache; + rf->fci_cache = fci_cache; } zend_hash_add_ptr(tmp_function_table, fn_str, rf); @@ -2115,7 +2111,7 @@ static PHP_FUNCTION(swoole_user_func_handler) { fci.params = ZEND_CALL_ARG(execute_data, 1); fci.named_params = NULL; ZVAL_UNDEF(&fci.function_name); - zend_call_function(&fci, rf->fci_cache); + zend_call_function(&fci, rf->fci_cache->ptr()); } zend_class_entry *find_class_entry(const char *name, size_t length) { diff --git a/ext-src/swoole_server.cc b/ext-src/swoole_server.cc index 2dfe4051d9a..84755385965 100644 --- a/ext-src/swoole_server.cc +++ b/ext-src/swoole_server.cc @@ -204,13 +204,12 @@ static void server_free_object(zend_object *object) { if (serv) { if (serv->private_data_3) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) serv->private_data_3); - efree(serv->private_data_3); + sw_callable_free(serv->private_data_3); } for (int i = 0; i < PHP_SWOOLE_SERVER_CALLBACK_NUM; i++) { - zend_fcall_info_cache *fci_cache = property->callbacks[i]; + auto fci_cache = property->callbacks[i]; if (fci_cache) { - efree(fci_cache); + sw_callable_free(fci_cache); property->callbacks[i] = nullptr; } } @@ -225,8 +224,7 @@ static void server_free_object(zend_object *object) { } for (auto fci_cache : property->command_callbacks) { - sw_zend_fci_cache_discard(fci_cache); - efree(fci_cache); + sw_callable_free(fci_cache); } delete property; @@ -633,18 +631,18 @@ void php_swoole_server_minit(int module_number) { SW_REGISTER_LONG_CONSTANT("SWOOLE_WORKER_EXIT", SW_WORKER_EXIT); } -zend_fcall_info_cache *php_swoole_server_get_fci_cache(Server *serv, int server_fd, int event_type) { +zend::Callable *php_swoole_server_get_callback(Server *serv, int server_fd, int event_type) { ListenPort *port = serv->get_port_by_server_fd(server_fd); ServerPortProperty *property = php_swoole_server_get_port_property(port); - zend_fcall_info_cache *fci_cache; + zend::Callable *cb; if (sw_unlikely(!port)) { return nullptr; } - if (property && (fci_cache = property->caches[event_type])) { - return fci_cache; + if (property && (cb = property->callbacks[event_type])) { + return cb; } else { - return php_swoole_server_get_port_property(serv->get_primary_port())->caches[event_type]; + return php_swoole_server_get_port_property(serv->get_primary_port())->callbacks[event_type]; } } @@ -1055,7 +1053,7 @@ static bool php_swoole_server_task_finish(Server *serv, zval *zdata, EventData * static void php_swoole_server_onPipeMessage(Server *serv, EventData *req) { ServerObject *server_object = server_fetch_object(Z_OBJ_P(php_swoole_server_zval_ptr(serv))); - zend_fcall_info_cache *fci_cache = server_object->property->callbacks[SW_SERVER_CB_onPipeMessage]; + auto cb = server_object->get_callback(SW_SERVER_CB_onPipeMessage); zval *zserv = php_swoole_server_zval_ptr(serv); zend::Variable zresult; @@ -1096,7 +1094,7 @@ static void php_swoole_server_onPipeMessage(Server *serv, EventData *req) { argc = 3; } - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, argc, args, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onPipeMessage handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1106,9 +1104,9 @@ static void php_swoole_server_onPipeMessage(Server *serv, EventData *req) { } int php_swoole_server_onReceive(Server *serv, RecvData *req) { - auto fci_cache = php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onReceive); + auto cb = php_swoole_server_get_callback(serv, req->info.server_fd, SW_SERVER_CB_onReceive); - if (fci_cache) { + if (cb) { zval *zserv = php_swoole_server_zval_ptr(serv); zval args[4]; int argc; @@ -1136,7 +1134,7 @@ int php_swoole_server_onReceive(Server *serv, RecvData *req) { argc = 4; } - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(cb, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onReceive handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); serv->close(req->info.fd, false); } @@ -1226,8 +1224,8 @@ int php_swoole_server_onPacket(Server *serv, RecvData *req) { argc = 3; } - auto fci_cache = php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onPacket); - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { + auto cb = php_swoole_server_get_callback(serv, req->info.server_fd, SW_SERVER_CB_onPacket); + if (UNEXPECTED(!zend::function::call(cb, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onPipeMessage handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1283,7 +1281,7 @@ static int php_swoole_server_onTask(Server *serv, EventData *req) { argv[3] = zresult.value; } - if (UNEXPECTED(!zend::function::call(server_object->property->callbacks[SW_SERVER_CB_onTask], + if (UNEXPECTED(!zend::function::call(server_object->get_callback(SW_SERVER_CB_onTask)->ptr(), argc, argv, &retval, @@ -1349,19 +1347,19 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { return SW_OK; } - zend_fcall_info_cache *fci_cache = nullptr; + zend::Callable *cb = nullptr; if (req->info.ext_flags & SW_TASK_CALLBACK) { auto callback_iterator = server_object->property->task_callbacks.find(task_id); if (callback_iterator == server_object->property->task_callbacks.end()) { req->info.ext_flags = req->info.ext_flags & (~SW_TASK_CALLBACK); } else { - fci_cache = &callback_iterator->second; + cb = callback_iterator->second; } } else { - fci_cache = server_object->property->callbacks[SW_SERVER_CB_onFinish]; + cb = server_object->get_callback(SW_SERVER_CB_onFinish); } - if (UNEXPECTED(fci_cache == nullptr)) { + if (UNEXPECTED(cb == nullptr)) { php_swoole_fatal_error(E_WARNING, "require 'onFinish' callback"); return SW_ERR; } @@ -1389,11 +1387,11 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { argc = 3; } - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(cb, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onFinish handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } if (req->info.ext_flags & SW_TASK_CALLBACK) { - sw_zend_fci_cache_discard(fci_cache); + sw_callable_free(server_object->property->task_callbacks[task_id]); server_object->property->task_callbacks.erase(task_id); } if (serv->event_object) { @@ -1404,10 +1402,9 @@ static int php_swoole_server_onFinish(Server *serv, EventData *req) { } static void php_swoole_server_onStart(Server *serv) { - serv->lock(); zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onStart]; + auto cb = server_object->get_callback(SW_SERVER_CB_onStart); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); @@ -1416,16 +1413,15 @@ static void php_swoole_server_onStart(Server *serv) { zend::function::call("\\Swoole\\Server\\Helper::onStart", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, serv->is_enable_coroutine()))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } - serv->unlock(); } static void php_swoole_server_onManagerStart(Server *serv) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStart]; + auto cb = server_object->get_callback(SW_SERVER_CB_onManagerStart); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); @@ -1434,7 +1430,7 @@ static void php_swoole_server_onManagerStart(Server *serv) { zend::function::call("\\Swoole\\Server\\Helper::onManagerStart", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onManagerStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1442,53 +1438,49 @@ static void php_swoole_server_onManagerStart(Server *serv) { static void php_swoole_server_onManagerStop(Server *serv) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onManagerStop]; + auto cb = server_object->get_callback(SW_SERVER_CB_onManagerStop); if (SWOOLE_G(enable_library)) { zend::function::call("\\Swoole\\Server\\Helper::onManagerStop", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onManagerStop handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } static void php_swoole_server_onBeforeShutdown(Server *serv) { - serv->lock(); zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeShutdown]; + auto cb = server_object->get_callback(SW_SERVER_CB_onBeforeShutdown); if (SWOOLE_G(enable_library)) { zend::function::call("\\Swoole\\Server\\Helper::onBeforeShutdown", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, serv->is_enable_coroutine()))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onBeforeShutdown handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } - serv->unlock(); } static void php_swoole_server_onShutdown(Server *serv) { - serv->lock(); zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onShutdown]; + auto cb = server_object->get_callback(SW_SERVER_CB_onShutdown); if (SWOOLE_G(enable_library)) { zend::function::call("\\Swoole\\Server\\Helper::onShutdown", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onShutdown handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } - serv->unlock(); } static void php_swoole_server_onWorkerStart(Server *serv, Worker *worker) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStart]; + auto cb = server_object->get_callback(SW_SERVER_CB_onWorkerStart); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("master_pid"), serv->gs->master_pid); zend_update_property_long(swoole_server_ce, SW_Z8_OBJ_P(zserv), ZEND_STRL("manager_pid"), serv->gs->manager_pid); @@ -1509,7 +1501,7 @@ static void php_swoole_server_onWorkerStart(Server *serv, Worker *worker) { zend::function::call("\\Swoole\\Server\\Helper::onWorkerStart", 2, args); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onWorkerStart handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1517,13 +1509,13 @@ static void php_swoole_server_onWorkerStart(Server *serv, Worker *worker) { static void php_swoole_server_onBeforeReload(Server *serv) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onBeforeReload]; + auto cb = server_object->get_callback(SW_SERVER_CB_onBeforeReload); if (SWOOLE_G(enable_library)) { zend::function::call("\\Swoole\\Server\\Helper::onBeforeReload", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onBeforeReload handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1531,13 +1523,13 @@ static void php_swoole_server_onBeforeReload(Server *serv) { static void php_swoole_server_onAfterReload(Server *serv) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onAfterReload]; + auto cb = server_object->get_callback(SW_SERVER_CB_onAfterReload); if (SWOOLE_G(enable_library)) { zend::function::call("\\Swoole\\Server\\Helper::onAfterReload", 1, zserv); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 1, zserv, nullptr, false))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 1, zserv, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onAfterReload handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1549,7 +1541,8 @@ static void php_swoole_server_onWorkerStop(Server *serv, Worker *worker) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerStop]; + auto cb = server_object->get_callback(SW_SERVER_CB_onWorkerStop); + zval args[2]; args[0] = *zserv; ZVAL_LONG(&args[1], worker->id); @@ -1558,7 +1551,7 @@ static void php_swoole_server_onWorkerStop(Server *serv, Worker *worker) { zend::function::call("\\Swoole\\Server\\Helper::onWorkerStop", 2, args); } - if (fci_cache && UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { + if (cb && UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onWorkerStop handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1566,7 +1559,7 @@ static void php_swoole_server_onWorkerStop(Server *serv, Worker *worker) { static void php_swoole_server_onWorkerExit(Server *serv, Worker *worker) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerExit]; + auto fci_cache = server_object->get_callback(SW_SERVER_CB_onWorkerExit); zval args[2]; args[0] = *zserv; @@ -1604,7 +1597,7 @@ static void php_swoole_server_onUserWorkerStart(Server *serv, Worker *worker) { static void php_swoole_server_onWorkerError(Server *serv, Worker *worker, const ExitStatus &exit_status) { zval *zserv = php_swoole_server_zval_ptr(serv); ServerObject *server_object = server_fetch_object(Z_OBJ_P(zserv)); - auto fci_cache = server_object->property->callbacks[SW_SERVER_CB_onWorkerError]; + auto fci_cache = server_object->get_callback(SW_SERVER_CB_onWorkerError); zval args[5]; int argc; @@ -1646,8 +1639,8 @@ static void php_swoole_server_onWorkerError(Server *serv, Worker *worker, const } void php_swoole_server_onConnect(Server *serv, DataHead *info) { - auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onConnect); - if (!fci_cache) { + auto cb = php_swoole_server_get_callback(serv, info->server_fd, SW_SERVER_CB_onConnect); + if (!cb) { return; } @@ -1671,7 +1664,7 @@ void php_swoole_server_onConnect(Server *serv, DataHead *info) { argc = 3; } - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(cb, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onConnect handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1700,7 +1693,7 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { } } - auto *fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onClose); + auto *cb = php_swoole_server_get_callback(serv, info->server_fd, SW_SERVER_CB_onClose); Connection *conn = serv->get_connection_by_session_id(session_id); if (!conn) { return; @@ -1709,10 +1702,10 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { ListenPort *port = serv->get_port_by_server_fd(info->server_fd); if (port && port->open_websocket_protocol && php_swoole_server_isset_callback(serv, port, SW_SERVER_CB_onDisconnect)) { - fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onDisconnect); + cb = php_swoole_server_get_callback(serv, info->server_fd, SW_SERVER_CB_onDisconnect); } } - if (fci_cache) { + if (cb) { zval *zserv = php_swoole_server_zval_ptr(serv); zval args[3]; int argc; @@ -1734,7 +1727,7 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { argc = 3; } - if (UNEXPECTED(!zend::function::call(fci_cache, argc, args, nullptr, serv->enable_coroutine))) { + if (UNEXPECTED(!zend::function::call(cb, argc, args, nullptr, serv->enable_coroutine))) { php_swoole_error(E_WARNING, "%s->onClose handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } @@ -1749,15 +1742,15 @@ void php_swoole_server_onClose(Server *serv, DataHead *info) { void php_swoole_server_onBufferFull(Server *serv, DataHead *info) { zval *zserv = php_swoole_server_zval_ptr(serv); - auto fci_cache = php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferFull); + auto cb = php_swoole_server_get_callback(serv, info->server_fd, SW_SERVER_CB_onBufferFull); - if (fci_cache) { + if (cb) { zval args[2]; args[0] = *zserv; ZVAL_LONG(&args[1], info->fd); - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onBufferFull handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -1798,9 +1791,7 @@ void php_swoole_server_send_yield(Server *serv, SessionId session_id, zval *zdat } static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendData *data) { - serv->lock(); - - auto fci_cache = (zend_fcall_info_cache *) serv->private_data_3; + auto cb = (zend::Callable *) serv->private_data_3; zval args[4]; zval *zserv = &args[0], *zfd = &args[1], *ztype = &args[2], *zdata = nullptr; zval retval; @@ -1809,12 +1800,12 @@ static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendD *zserv = *(php_swoole_server_zval_ptr(serv)); ZVAL_LONG(zfd, conn ? conn->session_id : data->info.fd); ZVAL_LONG(ztype, (zend_long) (data ? data->info.type : (int) SW_SERVER_EVENT_CLOSE)); - if (data && sw_zend_function_max_num_args(fci_cache->function_handler) > 3) { + if (data && sw_zend_function_max_num_args(cb->ptr()->function_handler) > 3) { // TODO: reduce memory copy zdata = &args[3]; ZVAL_STRINGL(zdata, data->data, data->info.len > SW_IPC_BUFFER_SIZE ? SW_IPC_BUFFER_SIZE : data->info.len); } - HOOK_PHP_CALL_STACK(auto call_result = sw_zend_call_function_ex(nullptr, fci_cache, zdata ? 4 : 3, args, &retval);); + HOOK_PHP_CALL_STACK(auto call_result = sw_zend_call_function_ex(nullptr, cb->ptr(), zdata ? 4 : 3, args, &retval);); if (UNEXPECTED(call_result != SUCCESS)) { php_swoole_error(E_WARNING, "%s->onDispatch handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } else if (!ZVAL_IS_NULL(&retval)) { @@ -1829,8 +1820,6 @@ static int php_swoole_server_dispatch_func(Server *serv, Connection *conn, SendD zval_ptr_dtor(zdata); } - serv->unlock(); - /* the exception should only be thrown after unlocked */ if (UNEXPECTED(EG(exception))) { zend_exception_error(EG(exception), E_ERROR); @@ -1857,15 +1846,14 @@ void php_swoole_server_onBufferEmpty(Server *serv, DataHead *info) { } } - zend_fcall_info_cache *fci_cache = - php_swoole_server_get_fci_cache(serv, info->server_fd, SW_SERVER_CB_onBufferEmpty); - if (fci_cache) { + auto cb = php_swoole_server_get_callback(serv, info->server_fd, SW_SERVER_CB_onBufferEmpty); + if (cb) { zval args[2]; args[0] = *zserv; ZVAL_LONG(&args[1], info->fd); - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, false))) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, false))) { php_swoole_error(E_WARNING, "%s->onBufferEmpty handler error", SW_Z_OBJCE_NAME_VAL_P(zserv)); } } @@ -2092,36 +2080,15 @@ static PHP_METHOD(swoole_server, set) { serv->send_yield = serv->enable_coroutine; } if (php_swoole_array_get_value(vht, "dispatch_func", ztmp)) { - Server::DispatchFunction c_dispatch_func = nullptr; - while (1) { - if (Z_TYPE_P(ztmp) == IS_STRING) { - c_dispatch_func = (Server::DispatchFunction) swoole_get_function(Z_STRVAL_P(ztmp), Z_STRLEN_P(ztmp)); - if (c_dispatch_func) { - break; - } - } -#ifdef ZTS - if (serv->is_process_mode() && !serv->single_thread) { - php_swoole_fatal_error(E_ERROR, "option [dispatch_func] does not support with ZTS"); - } -#endif - char *func_name = nullptr; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); - return; - } - efree(func_name); - sw_zend_fci_cache_persist(fci_cache); + auto fci_cache = sw_callable_create(ztmp); + if (fci_cache) { if (serv->private_data_3) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) serv->private_data_3); - efree(serv->private_data_3); + sw_callable_free(serv->private_data_3); } - serv->private_data_3 = (void *) fci_cache; - c_dispatch_func = php_swoole_server_dispatch_func; - break; + serv->private_data_3 = fci_cache; + serv->dispatch_func = php_swoole_server_dispatch_func; + serv->single_thread = true; } - serv->dispatch_func = c_dispatch_func; } /** * for dispatch_mode = 1/3 @@ -2438,14 +2405,6 @@ static PHP_METHOD(swoole_server, on) { Z_PARAM_ZVAL(cb) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - char *func_name = nullptr; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(cb, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); - return; - } - efree(func_name); - zend::String _event_name_ori(name); zend::String _event_name_tolower(zend_string_tolower(_event_name_ori.get()), false); @@ -2455,7 +2414,6 @@ static PHP_METHOD(swoole_server, on) { if (i == server_event_map.end()) { zval *port_object = server_object->property->ports.at(0); zval retval; - efree(fci_cache); sw_zend_call_method_with_2_params(port_object, swoole_server_port_ce, nullptr, "on", &retval, name, cb); RETURN_BOOL(Z_BVAL_P(&retval)); } else { @@ -2466,8 +2424,14 @@ static PHP_METHOD(swoole_server, on) { swoole_server_ce, SW_Z8_OBJ_P(ZEND_THIS), property_name.c_str(), property_name.length(), cb); if (server_object->property->callbacks[event_type]) { - efree(server_object->property->callbacks[event_type]); + sw_callable_free(server_object->property->callbacks[event_type]); + } + + auto fci_cache = sw_callable_create(cb); + if (!fci_cache) { + RETURN_FALSE; } + server_object->property->callbacks[event_type] = fci_cache; RETURN_TRUE; @@ -2594,13 +2558,12 @@ static PHP_METHOD(swoole_server, addCommand) { char *name; size_t l_name; zend_long accepted_process_types; - zend_fcall_info fci; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache)); + zval *zfn; ZEND_PARSE_PARAMETERS_START(3, 3) Z_PARAM_STRING(name, l_name) Z_PARAM_LONG(accepted_process_types) - Z_PARAM_FUNC(fci, *fci_cache) + Z_PARAM_ZVAL(zfn) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (accepted_process_types & Server::Command::REACTOR_THREAD) { @@ -2608,14 +2571,19 @@ static PHP_METHOD(swoole_server, addCommand) { RETURN_FALSE; } - Server::Command::Handler fn = [fci_cache](Server *serv, const std::string &msg) { + auto cb = sw_callable_create(zfn); + if (!cb) { + RETURN_FALSE; + } + + Server::Command::Handler fn = [cb](Server *serv, const std::string &msg) { zval *zserv = php_swoole_server_zval_ptr(serv); zval argv[2]; argv[0] = *zserv; ZVAL_STRINGL(&argv[1], msg.c_str(), msg.length()); zval return_value; - if (UNEXPECTED(!zend::function::call(fci_cache, 2, argv, &return_value, false))) { + if (UNEXPECTED(!zend::function::call(cb, 2, argv, &return_value, false))) { php_swoole_fatal_error(E_WARNING, "%s: command handler error", ZSTR_VAL(swoole_server_ce->name)); return std::string("{\"data\": \"failed to call function\", \"code\": -1}"); } @@ -2632,8 +2600,7 @@ static PHP_METHOD(swoole_server, addCommand) { } ServerObject *server_object = server_fetch_object(Z_OBJ_P(ZEND_THIS)); - sw_zend_fci_cache_persist(fci_cache); - server_object->property->command_callbacks.push_back(fci_cache); + server_object->property->command_callbacks.push_back(cb); RETURN_TRUE; } @@ -3351,14 +3318,13 @@ static PHP_METHOD(swoole_server, task) { zval *zdata; zend_long dst_worker_id = -1; - zend_fcall_info fci = empty_fcall_info; - zend_fcall_info_cache fci_cache = empty_fcall_info_cache; + zval *zfn = nullptr; ZEND_PARSE_PARAMETERS_START(1, 3) Z_PARAM_ZVAL(zdata) Z_PARAM_OPTIONAL Z_PARAM_LONG(dst_worker_id) - Z_PARAM_FUNC_EX(fci, fci_cache, 1, 0) + Z_PARAM_ZVAL(zfn) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); if (php_swoole_server_task_check_param(serv, dst_worker_id) < 0) { @@ -3373,10 +3339,13 @@ static PHP_METHOD(swoole_server, task) { if (!serv->is_worker()) { buf.info.ext_flags |= SW_TASK_NOREPLY; - } else if (fci.size) { + } else if (zfn && zval_is_true(zfn)) { buf.info.ext_flags |= SW_TASK_CALLBACK; - sw_zend_fci_cache_persist(&fci_cache); - server_object->property->task_callbacks[task_id] = fci_cache; + auto cb = sw_callable_create(zfn); + if (!cb) { + RETURN_FALSE; + } + server_object->property->task_callbacks[task_id] = cb; } buf.info.ext_flags |= SW_TASK_NONBLOCK; diff --git a/ext-src/swoole_server_port.cc b/ext-src/swoole_server_port.cc index 2feb2940353..9e5fdadb0a8 100644 --- a/ext-src/swoole_server_port.cc +++ b/ext-src/swoole_server_port.cc @@ -93,9 +93,9 @@ void php_swoole_server_port_deref(zend_object *object) { ServerPortProperty *property = &server_port->property; if (property->serv) { for (int j = 0; j < PHP_SWOOLE_SERVER_PORT_CALLBACK_NUM; j++) { - if (property->caches[j]) { - efree(property->caches[j]); - property->caches[j] = nullptr; + if (property->callbacks[j]) { + sw_callable_free(property->callbacks[j]); + property->callbacks[j] = nullptr; } } property->serv = nullptr; @@ -103,10 +103,9 @@ void php_swoole_server_port_deref(zend_object *object) { ListenPort *port = server_port->port; if (port) { - if (port->protocol.private_data) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) port->protocol.private_data); - efree(port->protocol.private_data); - port->protocol.private_data = nullptr; + if (port->protocol.private_data_1) { + sw_callable_free(port->protocol.private_data_1); + port->protocol.private_data_1 = nullptr; } server_port->port = nullptr; } @@ -192,16 +191,13 @@ void php_swoole_server_port_minit(int module_number) { * [Master/Worker] */ static ssize_t php_swoole_server_length_func(const Protocol *protocol, network::Socket *conn, PacketLength *pl) { - Server *serv = (Server *) protocol->private_data_2; - serv->lock(); - - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) protocol->private_data; + zend::Callable *cb = (zend::Callable *) protocol->private_data_1; zval zdata; zval retval; ssize_t ret = -1; ZVAL_STRINGL(&zdata, pl->buf, pl->buf_size); - HOOK_PHP_CALL_STACK(auto call_result = sw_zend_call_function_ex(nullptr, fci_cache, 1, &zdata, &retval);); + HOOK_PHP_CALL_STACK(auto call_result = sw_zend_call_function_ex(nullptr, cb->ptr(), 1, &zdata, &retval);); if (UNEXPECTED(call_result) != SUCCESS) { php_swoole_fatal_error(E_WARNING, "length function handler error"); } else { @@ -210,8 +206,6 @@ static ssize_t php_swoole_server_length_func(const Protocol *protocol, network:: } zval_ptr_dtor(&zdata); - serv->unlock(); - /* the exception should only be thrown after unlocked */ if (UNEXPECTED(EG(exception))) { zend_exception_error(EG(exception), E_ERROR); @@ -452,40 +446,18 @@ static PHP_METHOD(swoole_server_port, set) { } // length function if (php_swoole_array_get_value(vht, "package_length_func", ztmp)) { - while (1) { - if (Z_TYPE_P(ztmp) == IS_STRING) { - Protocol::LengthFunc func = Protocol::get_function(std::string(Z_STRVAL_P(ztmp), Z_STRLEN_P(ztmp))); - if (func != nullptr) { - port->protocol.get_package_length = func; - break; - } - } -#ifdef ZTS - Server *serv = property->serv; - if (serv->is_process_mode() && !serv->single_thread) { - php_swoole_fatal_error(E_ERROR, "option [package_length_func] does not support with ZTS"); - } -#endif - char *func_name; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); - return; - } - efree(func_name); + auto cb = sw_callable_create(ztmp); + if (cb) { port->protocol.get_package_length = php_swoole_server_length_func; - if (port->protocol.private_data) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) port->protocol.private_data); - efree(port->protocol.private_data); + if (port->protocol.private_data_1) { + sw_callable_free(port->protocol.private_data_1); } - sw_zend_fci_cache_persist(fci_cache); - port->protocol.private_data = fci_cache; - break; + port->protocol.private_data_1 = cb; + port->protocol.package_length_size = 0; + port->protocol.package_length_type = '\0'; + port->protocol.package_length_offset = SW_IPC_BUFFER_SIZE; + property->serv->single_thread = true; } - - port->protocol.package_length_size = 0; - port->protocol.package_length_type = '\0'; - port->protocol.package_length_offset = SW_IPC_BUFFER_SIZE; } /** * package max length @@ -632,13 +604,6 @@ static PHP_METHOD(swoole_server_port, on) { Z_PARAM_ZVAL(cb) ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE); - char *func_name = nullptr; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(cb, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_ERROR, "function '%s' is not callable", func_name); - return; - } - efree(func_name); bool found = false; for (auto i = server_port_event_map.begin(); i != server_port_event_map.end(); i++) { @@ -651,13 +616,16 @@ static PHP_METHOD(swoole_server_port, on) { std::string property_name = std::string("on") + i->second.name; zend_update_property( swoole_server_port_ce, SW_Z8_OBJ_P(ZEND_THIS), property_name.c_str(), property_name.length(), cb); - property->callbacks[index] = - sw_zend_read_property(swoole_server_port_ce, ZEND_THIS, property_name.c_str(), property_name.length(), 0); - sw_copy_to_stack(property->callbacks[index], property->_callbacks[index]); - if (property->caches[index]) { - efree(property->caches[index]); + + if (property->callbacks[index]) { + sw_callable_free(property->callbacks[index]); + } + + auto fci_cache = sw_callable_create(cb); + if (!fci_cache) { + RETURN_FALSE; } - property->caches[index] = fci_cache; + property->callbacks[index] = fci_cache; if (index == SW_SERVER_CB_onConnect && !serv->onConnect) { serv->onConnect = php_swoole_server_onConnect; @@ -675,7 +643,6 @@ static PHP_METHOD(swoole_server_port, on) { if (!found) { php_swoole_error(E_WARNING, "unknown event types[%s]", name); - efree(fci_cache); RETURN_FALSE; } RETURN_TRUE; diff --git a/ext-src/swoole_socket_coro.cc b/ext-src/swoole_socket_coro.cc index 0d316ae3082..cb7943f56ad 100644 --- a/ext-src/swoole_socket_coro.cc +++ b/ext-src/swoole_socket_coro.cc @@ -973,34 +973,17 @@ SW_API bool php_swoole_socket_set_protocol(Socket *sock, zval *zset) { } // length function if (php_swoole_array_get_value(vht, "package_length_func", ztmp)) { - do { - Protocol::LengthFunc func; - if (Z_TYPE_P(ztmp) == IS_STRING && - (func = Protocol::get_function(std::string(Z_STRVAL_P(ztmp), Z_STRLEN_P(ztmp))))) { - sock->protocol.get_package_length = func; - } else { - char *func_name; - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) ecalloc(1, sizeof(zend_fcall_info_cache)); - if (!sw_zend_is_callable_ex(ztmp, nullptr, 0, &func_name, nullptr, fci_cache, nullptr)) { - php_swoole_fatal_error(E_WARNING, "function '%s' is not callable", func_name); - efree(func_name); - efree(fci_cache); - ret = false; - break; - } - efree(func_name); - sock->protocol.get_package_length = php_swoole_length_func; - if (sock->protocol.private_data) { - sw_zend_fci_cache_discard((zend_fcall_info_cache *) sock->protocol.private_data); - efree(sock->protocol.private_data); - } - sw_zend_fci_cache_persist(fci_cache); - sock->protocol.private_data = fci_cache; + auto cb = sw_callable_create(ztmp); + if (cb) { + sock->protocol.get_package_length = php_swoole_length_func; + if (sock->protocol.private_data_1) { + sw_callable_free(sock->protocol.private_data_1); } + sock->protocol.private_data_1 = cb; sock->protocol.package_length_size = 0; sock->protocol.package_length_type = '\0'; sock->protocol.package_length_offset = SW_IPC_BUFFER_SIZE; - } while (0); + } } /** * package max length @@ -1344,13 +1327,12 @@ static PHP_METHOD(swoole_socket_coro, accept) { SocketObject *client_sock = (SocketObject *) socket_coro_fetch_object(client); client_sock->socket = conn; ZVAL_OBJ(return_value, &client_sock->std); - if (conn->protocol.private_data) { - zend_fcall_info_cache *fci_cache = (zend_fcall_info_cache *) emalloc(sizeof(*fci_cache)); - *fci_cache = *(zend_fcall_info_cache *) conn->protocol.private_data; - sw_zend_fci_cache_persist(fci_cache); - conn->protocol.private_data = fci_cache; - } socket_coro_init(return_value, client_sock); + // It must be copied once to avoid destroying the function when the connection closes. + if (sock->socket->protocol.private_data_1) { + zend::Callable *cb = (zend::Callable *) sock->socket->protocol.private_data_1; + conn->protocol.private_data_1 = cb->dup(); + } } else { socket_coro_sync_properties(ZEND_THIS, sock); RETURN_FALSE; @@ -1852,10 +1834,9 @@ static PHP_METHOD(swoole_socket_coro, close) { php_swoole_error(E_WARNING, "cannot close the referenced resource"); RETURN_FALSE; } - if (sock->socket->protocol.private_data) { - zend_fcall_info_cache *package_length_func = (zend_fcall_info_cache *) sock->socket->protocol.private_data; - sw_zend_fci_cache_discard(package_length_func); - efree(package_length_func); + if (sock->socket->protocol.private_data_1) { + sw_callable_free(sock->socket->protocol.private_data_1); + sock->socket->protocol.private_data_1 = nullptr; } if (!Z_ISUNDEF(sock->zstream)) { php_stream *stream = NULL; diff --git a/ext-src/swoole_websocket_server.cc b/ext-src/swoole_websocket_server.cc index 970649cca97..2808552b988 100644 --- a/ext-src/swoole_websocket_server.cc +++ b/ext-src/swoole_websocket_server.cc @@ -253,14 +253,13 @@ int php_swoole_websocket_frame_object_pack_ex(String *buffer, zval *zdata, zend_ } void swoole_websocket_onBeforeHandshakeResponse(Server *serv, int server_fd, HttpContext *ctx) { - zend_fcall_info_cache *fci_cache = - php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onBeforeHandshakeResponse); - if (fci_cache) { + auto cb = php_swoole_server_get_callback(serv, server_fd, SW_SERVER_CB_onBeforeHandshakeResponse); + if (cb) { zval args[3]; args[0] = *php_swoole_server_zval_ptr(serv); args[1] = *ctx->request.zobject; args[2] = *ctx->response.zobject; - if (UNEXPECTED(!zend::function::call(fci_cache, 3, args, nullptr, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, 3, args, nullptr, serv->is_enable_coroutine()))) { php_swoole_error( E_WARNING, "%s->onBeforeHandshakeResponse handler error", ZSTR_VAL(swoole_websocket_server_ce->name)); serv->close(ctx->fd, false); @@ -274,12 +273,12 @@ void swoole_websocket_onOpen(Server *serv, HttpContext *ctx) { swoole_error_log(SW_LOG_TRACE, SW_ERROR_SESSION_NOT_EXIST, "session[%ld] is closed", ctx->fd); return; } - zend_fcall_info_cache *fci_cache = php_swoole_server_get_fci_cache(serv, conn->server_fd, SW_SERVER_CB_onOpen); - if (fci_cache) { + auto cb = php_swoole_server_get_callback(serv, conn->server_fd, SW_SERVER_CB_onOpen); + if (cb) { zval args[2]; args[0] = *php_swoole_server_zval_ptr(serv); args[1] = *ctx->request.zobject; - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onOpen handler error", ZSTR_VAL(swoole_websocket_server_ce->name)); serv->close(ctx->fd, false); } @@ -557,15 +556,14 @@ int swoole_websocket_onMessage(Server *serv, RecvData *req) { } #endif - zend_fcall_info_cache *fci_cache = - php_swoole_server_get_fci_cache(serv, req->info.server_fd, SW_SERVER_CB_onMessage); + auto cb = php_swoole_server_get_callback(serv, req->info.server_fd, SW_SERVER_CB_onMessage); zval args[2]; args[0] = *php_swoole_server_zval_ptr(serv); php_swoole_websocket_construct_frame(&args[1], opcode, &zdata, flags); zend_update_property_long(swoole_websocket_frame_ce, SW_Z8_OBJ_P(&args[1]), ZEND_STRL("fd"), fd); - if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, nullptr, serv->is_enable_coroutine()))) { + if (UNEXPECTED(!zend::function::call(cb, 2, args, nullptr, serv->is_enable_coroutine()))) { php_swoole_error(E_WARNING, "%s->onMessage handler error", ZSTR_VAL(swoole_websocket_server_ce->name)); serv->close(fd, false); } diff --git a/include/swoole_c_api.h b/include/swoole_c_api.h index 28e27839068..2133b075612 100644 --- a/include/swoole_c_api.h +++ b/include/swoole_c_api.h @@ -45,9 +45,6 @@ enum swGlobalHookType { typedef void (*swHookFunc)(void *data); -int swoole_add_function(const char *name, void *func); -void *swoole_get_function(const char *name, uint32_t length); - int swoole_add_hook(enum swGlobalHookType type, swHookFunc cb, int push_back); void swoole_call_hook(enum swGlobalHookType type, void *arg); bool swoole_isset_hook(enum swGlobalHookType type); diff --git a/include/swoole_protocol.h b/include/swoole_protocol.h index e84b90665e9..179b4db9c32 100644 --- a/include/swoole_protocol.h +++ b/include/swoole_protocol.h @@ -46,7 +46,7 @@ struct Protocol { uint16_t package_body_offset; uint32_t package_max_length; - void *private_data; + void *private_data_1; void *private_data_2; /** @@ -67,10 +67,6 @@ struct Protocol { int recv_split_by_eof(network::Socket *socket, String *buffer); static ssize_t default_length_func(const Protocol *protocol, network::Socket *socket, PacketLength *pl); - - static inline LengthFunc get_function(const std::string &name) { - return (LengthFunc) swoole_get_function(name.c_str(), name.length()); - } }; } // namespace swoole diff --git a/include/swoole_server.h b/include/swoole_server.h index eeffcbb6895..81a3188dc1a 100644 --- a/include/swoole_server.h +++ b/include/swoole_server.h @@ -1337,14 +1337,6 @@ class Server { return &session_list[session_id % SW_SESSION_LIST_SIZE]; } - void lock() { - lock_.lock(); - } - - void unlock() { - lock_.unlock(); - } - void clear_timer(); static void timer_callback(Timer *timer, TimerNode *tnode); @@ -1577,6 +1569,14 @@ class Server { swoole_trace_log(SW_TRACE_SERVER, "schedule=%d, round=%d", key, worker_round_id); return key; } + + void lock() { + lock_.lock(); + } + + void unlock() { + lock_.unlock(); + } }; } // namespace swoole diff --git a/src/core/base.cc b/src/core/base.cc index 027e4dc63c7..6c4a1143e35 100644 --- a/src/core/base.cc +++ b/src/core/base.cc @@ -100,7 +100,6 @@ swoole::Global SwooleG = {}; __thread swoole::ThreadGlobal SwooleTG = {}; std::mutex sw_thread_lock; -static std::unordered_map functions; static swoole::Logger *g_logger_instance = nullptr; #ifdef __MACH__ @@ -217,27 +216,6 @@ void swoole_init(void) { SW_EXTERN_C_BEGIN -SW_API int swoole_add_function(const char *name, void *func) { - std::string _name(name); - auto iter = functions.find(_name); - if (iter != functions.end()) { - swoole_warning("Function '%s' has already been added", name); - return SW_ERR; - } else { - functions.emplace(std::make_pair(_name, func)); - return SW_OK; - } -} - -SW_API void *swoole_get_function(const char *name, uint32_t length) { - auto iter = functions.find(std::string(name, length)); - if (iter != functions.end()) { - return iter->second; - } else { - return nullptr; - } -} - SW_API int swoole_add_hook(enum swGlobalHookType type, swHookFunc func, int push_back) { assert(type <= SW_GLOBAL_HOOK_END); return swoole::hook_add(SwooleG.hooks, type, func, push_back); diff --git a/tests/swoole_http_server/callback_with_private.phpt b/tests/swoole_http_server/callback_with_private.phpt index d5b5ecae0db..e436119df06 100644 --- a/tests/swoole_http_server/callback_with_private.phpt +++ b/tests/swoole_http_server/callback_with_private.phpt @@ -38,10 +38,6 @@ $pm->run(true); //Fatal Error $pm->expectExitCode(255); $output = $pm->getChildOutput(); -if (PHP_VERSION_ID < 80000) { - Assert::contains($output, 'Swoole\Server::on() must be callable'); -} else { - Assert::contains($output, 'Swoole\Server::on(): function \'TestCo_9::foo\' is not callable'); -} +Assert::contains($output, "Swoole\Server\Port::on(): function 'TestCo_9::foo' is not callable"); ?> --EXPECT-- diff --git a/tests/swoole_http_server/callback_with_protected.phpt b/tests/swoole_http_server/callback_with_protected.phpt index 0af346d91d2..bf645080af7 100644 --- a/tests/swoole_http_server/callback_with_protected.phpt +++ b/tests/swoole_http_server/callback_with_protected.phpt @@ -34,10 +34,6 @@ $pm = ProcessManager::exec(function ($pm) { //Fatal Error $pm->expectExitCode(255); $output = $pm->getChildOutput(); -if (PHP_VERSION_ID < 80000) { - Assert::contains($output, 'Swoole\Server::on() must be callable'); -} else { - Assert::contains($output, 'Swoole\Server::on(): function \'TestCo::foo\' is not callable'); -} +Assert::contains($output, 'Swoole\Server\Port::on(): function \'TestCo::foo\' is not callable'); ?> --EXPECT-- diff --git a/tests/swoole_process/null_callback.phpt b/tests/swoole_process/null_callback.phpt index dfdc67f8ac6..faa89a89ff1 100644 --- a/tests/swoole_process/null_callback.phpt +++ b/tests/swoole_process/null_callback.phpt @@ -14,4 +14,4 @@ $process->start(); ?> --EXPECTF-- -Fatal error: Swoole\Process::start(): Illegal callback function of Swoole\Process in %s +Warning: Swoole\Process::start(): illegal callback function in %s