Skip to content

Commit

Permalink
Fix STDIN/STDOUT constants undefined in thread, Optimize fatal_error
Browse files Browse the repository at this point in the history
  • Loading branch information
matyhtf committed May 29, 2024
1 parent 6c33623 commit 1cfcdd9
Show file tree
Hide file tree
Showing 15 changed files with 236 additions and 32 deletions.
26 changes: 24 additions & 2 deletions ext-src/php_swoole.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "php_swoole_cxx.h"
#include "php_swoole_library.h"
#include "php_swoole_process.h"
#include "php_swoole_thread.h"

#if (HAVE_PCRE || HAVE_BUNDLED_PCRE) && !defined(COMPILE_DL_PCRE)
#include "ext/pcre/php_pcre.h"
Expand Down Expand Up @@ -87,6 +88,7 @@ static PHP_FUNCTION(swoole_mime_type_list);
static PHP_FUNCTION(swoole_substr_unserialize);
static PHP_FUNCTION(swoole_substr_json_decode);
static PHP_FUNCTION(swoole_internal_call_user_shutdown_begin);
static PHP_FUNCTION(swoole_test_fn); // only for unit tests
SW_EXTERN_C_END

// clang-format off
Expand Down Expand Up @@ -125,6 +127,7 @@ const zend_function_entry swoole_functions[] = {
PHP_FE(swoole_clear_dns_cache, arginfo_swoole_clear_dns_cache)
PHP_FE(swoole_substr_unserialize, arginfo_swoole_substr_unserialize)
PHP_FE(swoole_substr_json_decode, arginfo_swoole_substr_json_decode)
PHP_FE(swoole_test_fn, arginfo_swoole_test_fn)
PHP_FE(swoole_internal_call_user_shutdown_begin, arginfo_swoole_internal_call_user_shutdown_begin)
// for admin server
ZEND_FE(swoole_get_objects, arginfo_swoole_get_objects)
Expand Down Expand Up @@ -356,8 +359,14 @@ static void fatal_error(int code, const char *format, ...) {
zend_throw_exception(swoole_error_ce, swoole::std_string::vformat(format, args).c_str(), code);
va_end(args);

zend_exception_error(exception, E_ERROR);
exit(255);
zend::print_error(exception, E_ERROR);

#ifdef SW_THREAD
if (!tsrm_is_main_thread()) {
php_swoole_thread_bailout();
}
#endif
swoole_exit(255);
}

static void bug_report_message_init() {
Expand Down Expand Up @@ -1453,3 +1462,16 @@ static PHP_FUNCTION(swoole_substr_json_decode) {
}
zend::json_decode(return_value, str + offset, length, options, depth);
}

static PHP_FUNCTION(swoole_test_fn) {
char *test_case;
size_t test_case_len;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_STRING(test_case, test_case_len)
ZEND_PARSE_PARAMETERS_END();

if (SW_STRCASEEQ(test_case, test_case_len, "fatal_error")) {
swoole_fatal_error(SW_ERROR_FOR_TEST, "test");
php_printf("never be executed here\n");
}
}
7 changes: 7 additions & 0 deletions ext-src/php_swoole_cxx.h
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,13 @@ static inline zval *object_get(zval *obj, const char *name, size_t l_name) {
return zend_read_property(Z_OBJCE_P(obj), Z_OBJ_P(obj), name, l_name, 1, &rv);
}

/**
* print exception, The virtual machine will not be terminated.
*/
static inline void print_error(zend_object *exception, int severity) {
zend_exception_error(exception, severity);
}

//-----------------------------------namespace end--------------------------------------------
} // namespace zend

Expand Down
1 change: 1 addition & 0 deletions ext-src/php_swoole_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ ThreadResource *php_swoole_thread_resource_fetch(ThreadResourceId resource_id);
void php_swoole_thread_start(zend_string *file, zend_string *argv);
zend_string *php_swoole_thread_serialize(zval *zdata);
bool php_swoole_thread_unserialize(zend_string *data, zval *zv);
void php_swoole_thread_bailout(void);

zval *php_swoole_thread_get_arguments();

Expand Down
6 changes: 6 additions & 0 deletions ext-src/stubs/php_swoole.stub.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,9 @@ function swoole_substr_json_decode(string $str, int $offset, int $length = 0, bo
function swoole_internal_call_user_shutdown_begin(): bool
{
}


function swoole_test_fn(string $case): void
{

}
6 changes: 5 additions & 1 deletion ext-src/stubs/php_swoole_arginfo.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 1ab45a47bad71a13ad16c3d92dcb8612920ae84c */
* Stub hash: ac43701147665b52de0dce97b7581d37183158a1 */

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_version, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
Expand Down Expand Up @@ -129,3 +129,7 @@ ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_internal_call_user_shutdown_begin, 0, 0, _IS_BOOL, 0)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_swoole_test_fn, 0, 1, IS_VOID, 0)
ZEND_ARG_TYPE_INFO(0, case, IS_STRING, 0)
ZEND_END_ARG_INFO()
1 change: 0 additions & 1 deletion ext-src/swoole_coroutine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,6 @@ void PHPCoroutine::deactivate(void *ptr) {

void PHPCoroutine::shutdown() {
interrupt_thread_stop();
Coroutine::bailout(nullptr);
if (options) {
zend_array_destroy(options);
options = nullptr;
Expand Down
64 changes: 57 additions & 7 deletions ext-src/swoole_thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ static void php_swoole_thread_join(zend_object *object);
static void php_swoole_thread_create(INTERNAL_FUNCTION_PARAMETERS, zval *zobject);
static int php_swoole_thread_stream_fileno(zval *zstream);
static bool php_swoole_thread_stream_restore(zend_long sockfd, zval *return_value);
static void php_swoole_thread_register_stdio_file_handles(bool no_close);

static thread_local zval thread_argv;
static thread_local JMP_BUF *thread_bailout = nullptr;
static zend_long thread_resource_id = 0;
static std::unordered_map<ThreadResourceId, ThreadResource *> thread_resources;

Expand Down Expand Up @@ -298,6 +300,45 @@ void php_swoole_thread_rshutdown() {
}
}

static void php_swoole_thread_register_stdio_file_handles(bool no_close) {
php_stream *s_in, *s_out, *s_err;
php_stream_context *sc_in = NULL, *sc_out = NULL, *sc_err = NULL;
zend_constant ic, oc, ec;

s_in = php_stream_open_wrapper_ex("php://stdin", "rb", 0, NULL, sc_in);
s_out = php_stream_open_wrapper_ex("php://stdout", "wb", 0, NULL, sc_out);
s_err = php_stream_open_wrapper_ex("php://stderr", "wb", 0, NULL, sc_err);

if (s_in == NULL || s_out == NULL || s_err == NULL) {
if (s_in) php_stream_close(s_in);
if (s_out) php_stream_close(s_out);
if (s_err) php_stream_close(s_err);
return;
}

if (no_close) {
s_in->flags |= PHP_STREAM_FLAG_NO_CLOSE;
s_out->flags |= PHP_STREAM_FLAG_NO_CLOSE;
s_err->flags |= PHP_STREAM_FLAG_NO_CLOSE;
}

php_stream_to_zval(s_in, &ic.value);
php_stream_to_zval(s_out, &oc.value);
php_stream_to_zval(s_err, &ec.value);

ZEND_CONSTANT_SET_FLAGS(&ic, CONST_CS, 0);
ic.name = zend_string_init_interned("STDIN", sizeof("STDIN") - 1, 0);
zend_register_constant(&ic);

ZEND_CONSTANT_SET_FLAGS(&oc, CONST_CS, 0);
oc.name = zend_string_init_interned("STDOUT", sizeof("STDOUT") - 1, 0);
zend_register_constant(&oc);

ZEND_CONSTANT_SET_FLAGS(&ec, CONST_CS, 0);
ec.name = zend_string_init_interned("STDERR", sizeof("STDERR") - 1, 0);
zend_register_constant(&ec);
}

static void php_swoole_thread_create(INTERNAL_FUNCTION_PARAMETERS, zval *zobject) {
char *script_file;
size_t l_script_file;
Expand Down Expand Up @@ -366,6 +407,7 @@ void php_swoole_thread_start(zend_string *file, zend_string *argv_serialized) {
file_handle.primary_script = 1;

zend_first_try {
thread_bailout = EG(bailout);
if (argv_serialized == nullptr || ZSTR_LEN(argv_serialized) == 0) {
array_init(&thread_argv);
} else {
Expand All @@ -377,11 +419,13 @@ void php_swoole_thread_start(zend_string *file, zend_string *argv_serialized) {
zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGV), &global_argv);
zend_hash_update(&EG(symbol_table), ZSTR_KNOWN(ZEND_STR_ARGC), &global_argc);
}
php_swoole_thread_register_stdio_file_handles(true);
php_execute_script(&file_handle);
}
zend_end_try();

zend_destroy_file_handle(&file_handle);

php_request_shutdown(NULL);
file_handle.filename = NULL;

Expand All @@ -394,6 +438,13 @@ void php_swoole_thread_start(zend_string *file, zend_string *argv_serialized) {
swoole_thread_clean();
}

void php_swoole_thread_bailout(void) {
if (thread_bailout) {
EG(bailout) = thread_bailout;
zend_bailout();
}
}

static int php_swoole_thread_stream_fileno(zval *zstream) {
php_stream *stream;
int sockfd;
Expand Down Expand Up @@ -509,15 +560,14 @@ void ArrayItem::release() {
}
}

#define INIT_DECR_VALUE(v) \
zval rvalue = *v;\
if (Z_TYPE_P(v) == IS_DOUBLE) {\
rvalue.value.dval = -rvalue.value.dval;\
} else {\
ZVAL_LONG(&rvalue, -zval_get_long(v)); \
#define INIT_DECR_VALUE(v) \
zval rvalue = *v; \
if (Z_TYPE_P(v) == IS_DOUBLE) { \
rvalue.value.dval = -rvalue.value.dval; \
} else { \
ZVAL_LONG(&rvalue, -zval_get_long(v)); \
}


void ZendArray::incr_update(ArrayItem *item, zval *zvalue, zval *return_value) {
if (item->type == IS_DOUBLE) {
item->value.dval += zval_get_double(zvalue);
Expand Down
9 changes: 5 additions & 4 deletions include/swoole.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,8 +123,8 @@ typedef unsigned long ulong_t;
#define SW_ECHO_LEN_CYAN "\e[36m%.*s\e[0m"
#define SW_ECHO_LEN_WHITE "\e[37m%.*s\e[0m"

#define SW_ECHO_RED_BG "\e[41m%s\e[0m"
#define SW_ECHO_GREEN_BG "\e[42m%s\e[0m"
#define SW_ECHO_RED_BG "\e[41m%s\e[0m"
#define SW_ECHO_GREEN_BG "\e[42m%s\e[0m"

#define SW_COLOR_RED 1
#define SW_COLOR_GREEN 2
Expand Down Expand Up @@ -581,6 +581,7 @@ int swoole_get_systemd_listen_fds();

void swoole_init(void);
void swoole_clean(void);
void swoole_exit(int __status);
pid_t swoole_fork(int flags);
pid_t swoole_fork_exec(const std::function<void(void)> &child_fn);
void swoole_thread_init(void);
Expand All @@ -601,7 +602,8 @@ typedef cpuset_t cpu_set_t;
int swoole_set_cpu_affinity(cpu_set_t *set);
#endif

#if defined(_POSIX_TIMERS) && ((_POSIX_TIMERS > 0) || defined(__OpenBSD__)) && defined(_POSIX_MONOTONIC_CLOCK) && defined(CLOCK_MONOTONIC)
#if defined(_POSIX_TIMERS) && ((_POSIX_TIMERS > 0) || defined(__OpenBSD__)) && defined(_POSIX_MONOTONIC_CLOCK) && \
defined(CLOCK_MONOTONIC)
#ifndef HAVE_CLOCK_GETTIME
#define HAVE_CLOCK_GETTIME
#endif
Expand Down Expand Up @@ -907,4 +909,3 @@ static sw_inline swoole::MemoryPool *sw_mem_pool() {
static sw_inline const swoole::Allocator *sw_std_allocator() {
return &SwooleG.std_allocator;
}

2 changes: 2 additions & 0 deletions include/swoole_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ enum swErrorCode {
SW_ERROR_PROTOCOL_ERROR,
SW_ERROR_WRONG_OPERATION,
SW_ERROR_PHP_RUNTIME_NOTICE, // Non-fatal errors, just runtime warnings
SW_ERROR_FOR_TEST,

SW_ERROR_UNDEFINED_BEHAVIOR = 600,
SW_ERROR_NOT_THREAD_SAFETY,

Expand Down
26 changes: 11 additions & 15 deletions include/swoole_log.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,21 +88,21 @@ swoole::Logger *sw_logger();
#define __SW_FUNC__ (swoole::Logger::get_pretty_name(__PRETTY_FUNCTION__).c_str())

#define swoole_info(str, ...) \
if (SW_LOG_INFO >= swoole_get_log_level()) { \
if (SW_LOG_INFO >= swoole_get_log_level()) { \
size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \
sw_logger()->put(SW_LOG_INFO, sw_error, _sw_error_len); \
}

#define swoole_notice(str, ...) \
if (SW_LOG_NOTICE >= swoole_get_log_level()) { \
if (SW_LOG_NOTICE >= swoole_get_log_level()) { \
size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \
sw_logger()->put(SW_LOG_NOTICE, sw_error, _sw_error_len); \
}

#define swoole_sys_notice(str, ...) \
do { \
swoole_set_last_error(errno); \
if (SW_LOG_ERROR >= swoole_get_log_level()) { \
if (SW_LOG_ERROR >= swoole_get_log_level()) { \
size_t _sw_error_len = sw_snprintf(sw_error, \
SW_ERROR_MSG_SIZE, \
"%s(:%d): " str ", Error: %s[%d]", \
Expand All @@ -117,7 +117,7 @@ swoole::Logger *sw_logger();

#define swoole_warning(str, ...) \
do { \
if (SW_LOG_WARNING >= swoole_get_log_level()) { \
if (SW_LOG_WARNING >= swoole_get_log_level()) { \
size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(): " str, __SW_FUNC__, ##__VA_ARGS__); \
sw_logger()->put(SW_LOG_WARNING, sw_error, _sw_error_len); \
} \
Expand All @@ -126,7 +126,7 @@ swoole::Logger *sw_logger();
#define swoole_sys_warning(str, ...) \
do { \
swoole_set_last_error(errno); \
if (SW_LOG_ERROR >= swoole_get_log_level()) { \
if (SW_LOG_ERROR >= swoole_get_log_level()) { \
size_t _sw_error_len = sw_snprintf(sw_error, \
SW_ERROR_MSG_SIZE, \
"%s(): " str ", Error: %s[%d]", \
Expand All @@ -142,7 +142,7 @@ swoole::Logger *sw_logger();
do { \
size_t _sw_error_len = sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, str, ##__VA_ARGS__); \
sw_logger()->put(SW_LOG_ERROR, sw_error, _sw_error_len); \
exit(1); \
swoole_exit(1); \
} while (0)

#define swoole_sys_error(str, ...) \
Expand All @@ -155,19 +155,15 @@ swoole::Logger *sw_logger();
swoole_strerror(errno), \
errno); \
sw_logger()->put(SW_LOG_ERROR, sw_error, _sw_error_len); \
exit(1); \
swoole_exit(1); \
} while (0)

#define swoole_fatal_error(code, str, ...) \
do { \
SwooleG.fatal_error(code, str, ##__VA_ARGS__); \
exit(255); \
} while (0)
#define swoole_fatal_error(code, str, ...) SwooleG.fatal_error(code, str, ##__VA_ARGS__)

#define swoole_error_log(level, error, str, ...) \
do { \
swoole_set_last_error(error); \
if (level >= swoole_get_log_level() && !swoole_is_ignored_error(error)) { \
if (level >= swoole_get_log_level() && !swoole_is_ignored_error(error)) { \
size_t _sw_error_len = \
sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s() (ERRNO %d): " str, __SW_FUNC__, error, ##__VA_ARGS__); \
sw_logger()->put(level, sw_error, _sw_error_len); \
Expand All @@ -176,7 +172,7 @@ swoole::Logger *sw_logger();

#ifdef SW_DEBUG
#define swoole_debug(str, ...) \
if (SW_LOG_DEBUG >= swoole_get_log_level()) { \
if (SW_LOG_DEBUG >= swoole_get_log_level()) { \
size_t _sw_error_len = \
sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \
sw_logger()->put(SW_LOG_DEBUG, sw_error, _sw_error_len); \
Expand Down Expand Up @@ -256,7 +252,7 @@ enum swTraceWhat : long {

#ifdef SW_LOG_TRACE_OPEN
#define swoole_trace_log(what, str, ...) \
if (SW_LOG_TRACE >= swoole_get_log_level() && (what & SwooleG.trace_flags)) { \
if (SW_LOG_TRACE >= swoole_get_log_level() && (what & SwooleG.trace_flags)) { \
size_t _sw_error_len = \
sw_snprintf(sw_error, SW_ERROR_MSG_SIZE, "%s(:%d): " str, __SW_FUNC__, __LINE__, ##__VA_ARGS__); \
sw_logger()->put(SW_LOG_TRACE, sw_error, _sw_error_len); \
Expand Down
9 changes: 8 additions & 1 deletion src/core/base.cc
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,14 @@ static void swoole_fatal_error_impl(int code, const char *format, ...) {
retval += sw_vsnprintf(sw_error + retval, SW_ERROR_MSG_SIZE - retval, format, args);
va_end(args);
sw_logger()->put(SW_LOG_ERROR, sw_error, retval);
exit(1);
swoole_exit(1);
}

void swoole_exit(int __status) {
#ifdef SW_THREAD
std::unique_lock<std::mutex> _lock(sw_thread_lock);
#endif
exit(__status);
}

namespace swoole {
Expand Down
2 changes: 1 addition & 1 deletion src/server/master.cc
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ int Server::start_master_thread(Reactor *reactor) {
}

#ifdef HAVE_PTHREAD_BARRIER
if (is_process_mode() && !single_thread) {
if (!single_thread) {
pthread_barrier_wait(&reactor_thread_barrier);
}
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
Expand Down
Loading

0 comments on commit 1cfcdd9

Please sign in to comment.