Skip to content

Commit

Permalink
fix native-curl crash on PHP8 (#4045)
Browse files Browse the repository at this point in the history
* fix native-curl crash on PHP8

* optimize code

* optimize code[2]

* fix tests

* optimize code[3]

* fix tests
  • Loading branch information
matyhtf authored Feb 7, 2021
1 parent 6d9b69e commit 289e673
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 157 deletions.
67 changes: 35 additions & 32 deletions ext-src/swoole_runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@
#include "swoole_util.h"

#include "thirdparty/php/standard/proc_open.h"
#include "thirdparty/php/curl/curl_arginfo.h"
#ifdef SW_USE_CURL
#include "thirdparty/php/curl/curl_interface.h"
#endif

#include <unordered_map>
#include <initializer_list>
Expand Down Expand Up @@ -54,12 +56,6 @@ static PHP_FUNCTION(swoole_time_sleep_until);
static PHP_FUNCTION(swoole_stream_select);
static PHP_FUNCTION(swoole_stream_socket_pair);
static PHP_FUNCTION(swoole_user_func_handler);

#ifdef SW_USE_CURL
void swoole_native_curl_init(int module_number);
void swoole_native_curl_shutdown();
#endif

SW_EXTERN_C_END

static int socket_set_option(php_stream *stream, int option, int value, void *ptrparam);
Expand Down Expand Up @@ -144,10 +140,18 @@ static php_stream_ops ori_php_stream_stdio_ops;

static void hook_func(const char *name, size_t l_name, zif_handler handler = nullptr, zend_internal_arg_info *arg_info = nullptr);
static void unhook_func(const char *name, size_t l_name);
static bool hook_internal_functions(const zend_function_entry *fes);

static zend_internal_arg_info *get_arginfo(const char *name, size_t l_name) {
zend_function *zf = (zend_function *) zend_hash_str_find_ptr(EG(function_table), name, l_name);
if (zf == nullptr) {
return nullptr;
}
return zf->internal_function.arg_info;
}

#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_NATIVE_FUNC_WITH_ARG_INFO(f) hook_func(ZEND_STRL(#f), PHP_FN(swoole_native_##f), get_arginfo(ZEND_STRL("swoole_native_" #f)))

static zend_array *tmp_function_table = nullptr;

Expand Down Expand Up @@ -179,7 +183,7 @@ void php_swoole_runtime_minit(int module_number) {
SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_SOCKETS", PHPCoroutine::HOOK_SOCKETS);
SW_REGISTER_LONG_CONSTANT("SWOOLE_HOOK_ALL", PHPCoroutine::HOOK_ALL);
#ifdef SW_USE_CURL
swoole_native_curl_init(module_number);
swoole_native_curl_minit(module_number);
#endif
swoole_proc_open_init(module_number);
}
Expand Down Expand Up @@ -221,7 +225,7 @@ void php_swoole_runtime_rshutdown() {

void php_swoole_runtime_mshutdown() {
#ifdef SW_USE_CURL
swoole_native_curl_shutdown();
swoole_native_curl_mshutdown();
#endif
}

Expand Down Expand Up @@ -1384,23 +1388,19 @@ bool PHPCoroutine::enable_hook(uint32_t flags) {
flags ^= PHPCoroutine::HOOK_CURL;
}
if (!(runtime_hook_flags & PHPCoroutine::HOOK_NATIVE_CURL)) {
#if PHP_VERSION_ID >= 80000
hook_internal_functions(swoole_native_curl_functions);
#else
hook_func(ZEND_STRL("curl_close"), PHP_FN(swoole_native_curl_close));
hook_func(ZEND_STRL("curl_copy_handle"), PHP_FN(swoole_native_curl_copy_handle));
hook_func(ZEND_STRL("curl_errno"), PHP_FN(swoole_native_curl_errno));
hook_func(ZEND_STRL("curl_error"), PHP_FN(swoole_native_curl_error));
hook_func(ZEND_STRL("curl_exec"), PHP_FN(swoole_native_curl_exec));
hook_func(ZEND_STRL("curl_getinfo"), PHP_FN(swoole_native_curl_getinfo));
hook_func(ZEND_STRL("curl_init"), PHP_FN(swoole_native_curl_init));
hook_func(ZEND_STRL("curl_setopt"), PHP_FN(swoole_native_curl_setopt));
hook_func(ZEND_STRL("curl_setopt_array"), PHP_FN(swoole_native_curl_setopt_array));
hook_func(ZEND_STRL("curl_reset"), PHP_FN(swoole_native_curl_reset));
hook_func(ZEND_STRL("curl_pause"), PHP_FN(swoole_native_curl_pause));
hook_func(ZEND_STRL("curl_escape"), PHP_FN(swoole_native_curl_escape));
hook_func(ZEND_STRL("curl_unescape"), PHP_FN(swoole_native_curl_unescape));
#endif
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_close);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_copy_handle);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_errno);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_error);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_exec);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_getinfo);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_init);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_setopt);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_setopt_array);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_reset);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_pause);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_escape);
SW_HOOK_NATIVE_FUNC_WITH_ARG_INFO(curl_unescape);
}
} else {
if (runtime_hook_flags & PHPCoroutine::HOOK_NATIVE_CURL) {
Expand Down Expand Up @@ -1804,11 +1804,6 @@ static PHP_FUNCTION(swoole_stream_select) {
RETURN_LONG(retval);
}

bool hook_internal_functions(const zend_function_entry *fes) {
zend_unregister_functions(fes, -1, CG(function_table));
return zend_register_functions(NULL, fes, NULL, MODULE_PERSISTENT) == SUCCESS;
}

static void hook_func(const char *name, size_t l_name, zif_handler handler, zend_internal_arg_info *arg_info) {
real_func *rf = (real_func *) zend_hash_str_find_ptr(tmp_function_table, name, l_name);
bool use_php_func = false;
Expand All @@ -1821,6 +1816,9 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend
}
if (rf) {
rf->function->internal_function.handler = handler;
if (arg_info) {
rf->function->internal_function.arg_info = arg_info;
}
return;
}

Expand All @@ -1833,7 +1831,11 @@ static void hook_func(const char *name, size_t l_name, zif_handler handler, zend
sw_memset_zero(rf, sizeof(*rf));
rf->function = zf;
rf->ori_handler = zf->internal_function.handler;
rf->ori_arg_info = zf->internal_function.arg_info;
zf->internal_function.handler = handler;
if (arg_info) {
zf->internal_function.arg_info = arg_info;
}

if (use_php_func) {
char func[128];
Expand Down Expand Up @@ -1861,6 +1863,7 @@ static void unhook_func(const char *name, size_t l_name) {
return;
}
rf->function->internal_function.handler = rf->ori_handler;
rf->function->internal_function.arg_info = rf->ori_arg_info;
}

php_stream *php_swoole_create_stream_from_socket(php_socket_t _fd, int domain, int type, int protocol STREAMS_DC) {
Expand Down
4 changes: 2 additions & 2 deletions src/core/base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ pid_t swoole_fork(int flags) {
/**
* [!!!] All timers and event loops must be cleaned up after fork
*/
if (SwooleTG.timer) {
if (swoole_timer_is_available()) {
swoole_timer_free();
}
if (SwooleG.memory_pool) {
Expand All @@ -288,7 +288,7 @@ pid_t swoole_fork(int flags) {
// reopen log file
sw_logger()->reopen();
// reset eventLoop
if (SwooleTG.reactor) {
if (swoole_event_is_available()) {
swoole_event_free();
swTraceLog(SW_TRACE_REACTOR, "reactor has been destroyed");
}
Expand Down
9 changes: 6 additions & 3 deletions src/core/timer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ int swoole_clock_gettime(int which_clock, struct timespec *t) {

namespace swoole {

Timer::Timer()
: heap(1024, Heap::MIN_HEAP) {
Timer::Timer() : heap(1024, Heap::MIN_HEAP) {
_current_id = -1;
next_msec_ = -1;
_next_id = 1;
Expand Down Expand Up @@ -80,7 +79,11 @@ bool Timer::init_reactor(Reactor *reactor) {
reactor->set_exit_condition(Reactor::EXIT_CONDITION_TIMER,
[this](Reactor *reactor, int &event_num) -> bool { return count() == 0; });

reactor->add_destroy_callback([](void *) { swoole_timer_free(); });
reactor->add_destroy_callback([](void *) {
if (swoole_timer_is_available()) {
swoole_timer_free();
}
});

return true;
}
Expand Down
71 changes: 21 additions & 50 deletions thirdparty/php/curl/curl_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,38 +1,9 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: f1d616c644ad366405816cde0384f6f391773ebf */

#ifdef SW_USE_CURL

#include "zend_API.h"

#include <curl/curl.h>
#include <curl/multi.h>

SW_EXTERN_C_BEGIN
PHP_FUNCTION(swoole_native_curl_close);
PHP_FUNCTION(swoole_native_curl_copy_handle);
PHP_FUNCTION(swoole_native_curl_errno);
PHP_FUNCTION(swoole_native_curl_error);
PHP_FUNCTION(swoole_native_curl_exec);
PHP_FUNCTION(swoole_native_curl_getinfo);
PHP_FUNCTION(swoole_native_curl_init);
PHP_FUNCTION(swoole_native_curl_setopt);
PHP_FUNCTION(swoole_native_curl_setopt_array);

#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
PHP_FUNCTION(swoole_native_curl_reset);
#endif

#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
PHP_FUNCTION(swoole_native_curl_escape);
PHP_FUNCTION(swoole_native_curl_unescape);
#endif

#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
PHP_FUNCTION(swoole_native_curl_pause);
#endif
SW_EXTERN_C_END
#include "curl_interface.h"

#ifdef SW_USE_CURL
#if PHP_VERSION_ID >= 80000

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_close, 0, 1, IS_VOID, 0)
Expand Down Expand Up @@ -102,25 +73,25 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_native_curl_setopt, 0, 3,
ZEND_END_ARG_INFO()

static const zend_function_entry swoole_native_curl_functions[] = {
ZEND_FENTRY(curl_close, PHP_FN(swoole_native_curl_close), arginfo_swoole_native_curl_close, 0)
ZEND_FENTRY(curl_copy_handle, PHP_FN(swoole_native_curl_copy_handle), arginfo_swoole_native_curl_copy_handle, 0)
ZEND_FENTRY(curl_errno, PHP_FN(swoole_native_curl_errno), arginfo_swoole_native_curl_errno, 0)
ZEND_FENTRY(curl_error, PHP_FN(swoole_native_curl_error), arginfo_swoole_native_curl_error, 0)
ZEND_FENTRY(curl_exec, PHP_FN(swoole_native_curl_exec), arginfo_swoole_native_curl_exec, 0)
ZEND_FENTRY(curl_getinfo, PHP_FN(swoole_native_curl_getinfo), arginfo_swoole_native_curl_getinfo, 0)
ZEND_FENTRY(curl_init, PHP_FN(swoole_native_curl_init), arginfo_swoole_native_curl_init, 0)
ZEND_FENTRY(curl_setopt, PHP_FN(swoole_native_curl_setopt), arginfo_swoole_native_curl_setopt, 0)
ZEND_FENTRY(curl_setopt_array, PHP_FN(swoole_native_curl_setopt_array), arginfo_swoole_native_curl_setopt_array, 0)
#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
ZEND_FENTRY(curl_reset, PHP_FN(swoole_native_curl_reset), arginfo_swoole_native_curl_reset, 0)
#endif
#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
ZEND_FENTRY(curl_escape, PHP_FN(swoole_native_curl_escape), arginfo_swoole_native_curl_escape, 0)
ZEND_FENTRY(curl_unescape, PHP_FN(swoole_native_curl_unescape), arginfo_swoole_native_curl_unescape, 0)
#endif
#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
ZEND_FENTRY(curl_pause, PHP_FN(swoole_native_curl_pause), arginfo_swoole_native_curl_pause, 0)
#endif
PHP_FE(swoole_native_curl_close, arginfo_swoole_native_curl_close)
PHP_FE(swoole_native_curl_copy_handle, arginfo_swoole_native_curl_copy_handle)
PHP_FE(swoole_native_curl_errno, arginfo_swoole_native_curl_errno)
PHP_FE(swoole_native_curl_error, arginfo_swoole_native_curl_error)
PHP_FE(swoole_native_curl_exec, arginfo_swoole_native_curl_exec)
PHP_FE(swoole_native_curl_getinfo, arginfo_swoole_native_curl_getinfo)
PHP_FE(swoole_native_curl_init, arginfo_swoole_native_curl_init)
PHP_FE(swoole_native_curl_setopt, arginfo_swoole_native_curl_setopt)
PHP_FE(swoole_native_curl_setopt_array, arginfo_swoole_native_curl_setopt_array)
#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
PHP_FE(swoole_native_curl_reset, arginfo_swoole_native_curl_reset)
#endif
#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
PHP_FE(swoole_native_curl_escape, arginfo_swoole_native_curl_escape)
PHP_FE(swoole_native_curl_unescape, arginfo_swoole_native_curl_unescape)
#endif
#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
PHP_FE(swoole_native_curl_pause, arginfo_swoole_native_curl_pause)
#endif
PHP_FE_END
};
#endif
Expand Down
37 changes: 37 additions & 0 deletions thirdparty/php/curl/curl_interface.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include "php_swoole_cxx.h"

#ifdef SW_USE_CURL
SW_EXTERN_C_BEGIN

#include <curl/curl.h>
#include <curl/multi.h>

void swoole_native_curl_minit(int module_number);
void swoole_native_curl_mshutdown();

PHP_FUNCTION(swoole_native_curl_close);
PHP_FUNCTION(swoole_native_curl_copy_handle);
PHP_FUNCTION(swoole_native_curl_errno);
PHP_FUNCTION(swoole_native_curl_error);
PHP_FUNCTION(swoole_native_curl_exec);
PHP_FUNCTION(swoole_native_curl_getinfo);
PHP_FUNCTION(swoole_native_curl_init);
PHP_FUNCTION(swoole_native_curl_setopt);
PHP_FUNCTION(swoole_native_curl_setopt_array);

#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
PHP_FUNCTION(swoole_native_curl_reset);
#endif

#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
PHP_FUNCTION(swoole_native_curl_escape);
PHP_FUNCTION(swoole_native_curl_unescape);
#endif

#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
PHP_FUNCTION(swoole_native_curl_pause);
#endif
SW_EXTERN_C_END
#endif
7 changes: 3 additions & 4 deletions thirdparty/php/curl/curl_multi.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,10 @@
| Author: Tianfeng Han <[email protected]> |
+----------------------------------------------------------------------+
*/
#pragma once

#ifdef SW_USE_CURL

#pragma once

#include "php_swoole_cxx.h"
#include "swoole_util.h"

Expand Down Expand Up @@ -85,7 +84,7 @@ class cURLMulti {
}

void add_timer(long timeout_ms) {
if (timer) {
if (timer && swoole_timer_is_available()) {
swoole_timer_del(timer);
}

Expand All @@ -95,7 +94,7 @@ class cURLMulti {
}

void del_timer() {
if (timer) {
if (timer && swoole_timer_is_available()) {
swoole_timer_del(timer);
}
}
Expand Down
Loading

0 comments on commit 289e673

Please sign in to comment.