Skip to content

Commit 7d2de71

Browse files
author
rango
committed
Fix thread exit security issue
1 parent 6142b66 commit 7d2de71

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

ext-src/swoole_thread.cc

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ static void php_swoole_thread_register_stdio_file_handles(bool no_close);
5757

5858
static thread_local zval thread_argv = {};
5959
static thread_local JMP_BUF *thread_bailout = nullptr;
60+
static std::atomic<size_t> thread_num(1);
6061

6162
static sw_inline ThreadObject *thread_fetch_object(zend_object *obj) {
6263
return (ThreadObject *) ((char *) obj - swoole_thread_handlers.offset);
@@ -103,6 +104,7 @@ static const zend_function_entry swoole_thread_methods[] = {
103104
PHP_ME(swoole_thread, getArguments, arginfo_class_Swoole_Thread_getArguments, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
104105
PHP_ME(swoole_thread, getId, arginfo_class_Swoole_Thread_getId, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
105106
PHP_ME(swoole_thread, getTsrmInfo, arginfo_class_Swoole_Thread_getTsrmInfo, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
107+
PHP_MALIAS(swoole_thread, info, getTsrmInfo, arginfo_class_Swoole_Thread_getTsrmInfo, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
106108
PHP_FE_END
107109
};
108110
// clang-format on
@@ -245,15 +247,20 @@ void php_swoole_thread_rinit() {
245247

246248
void php_swoole_thread_rshutdown() {
247249
zval_dtor(&thread_argv);
248-
if (tsrm_is_main_thread()) {
249-
if (request_info.path_translated) {
250-
free((void *) request_info.path_translated);
251-
request_info.path_translated = nullptr;
252-
}
253-
if (request_info.argv_serialized) {
254-
zend_string_release(request_info.argv_serialized);
255-
request_info.argv_serialized = nullptr;
256-
}
250+
if (!tsrm_is_main_thread()) {
251+
return;
252+
}
253+
if (thread_num.load() > 1) {
254+
swoole_warning("Fatal Error: %zu active threads are running, cannot exit safely.", thread_num.load());
255+
exit(200);
256+
}
257+
if (request_info.path_translated) {
258+
free((void *) request_info.path_translated);
259+
request_info.path_translated = nullptr;
260+
}
261+
if (request_info.argv_serialized) {
262+
zend_string_release(request_info.argv_serialized);
263+
request_info.argv_serialized = nullptr;
257264
}
258265
}
259266

@@ -297,6 +304,7 @@ static void php_swoole_thread_register_stdio_file_handles(bool no_close) {
297304
}
298305

299306
void php_swoole_thread_start(zend_string *file, ZendArray *argv) {
307+
thread_num.fetch_add(1);
300308
ts_resource(0);
301309
#if defined(COMPILE_DL_SWOOLE) && defined(ZTS)
302310
ZEND_TSRMLS_CACHE_UPDATE();
@@ -355,6 +363,7 @@ void php_swoole_thread_start(zend_string *file, ZendArray *argv) {
355363
zend_string_release(file);
356364
ts_free_thread();
357365
swoole_thread_clean();
366+
thread_num.fetch_sub(1);
358367
}
359368

360369
void php_swoole_thread_bailout(void) {
@@ -426,6 +435,7 @@ static PHP_METHOD(swoole_thread, getTsrmInfo) {
426435
add_assoc_bool(return_value, "is_main_thread", tsrm_is_main_thread());
427436
add_assoc_bool(return_value, "is_shutdown", tsrm_is_shutdown());
428437
add_assoc_string(return_value, "api_name", tsrm_api_name());
438+
add_assoc_long(return_value, "thread_num", thread_num.load());
429439
}
430440

431441
#define CAST_OBJ_TO_RESOURCE(_name, _type) \
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
--TEST--
2+
swoole_thread: fatal error 3
3+
--SKIPIF--
4+
<?php
5+
require __DIR__ . '/../include/skipif.inc';
6+
skip_if_nts();
7+
?>
8+
--FILE--
9+
<?php
10+
require __DIR__ . '/../include/bootstrap.php';
11+
12+
use Swoole\Thread;
13+
use SwooleTest\ThreadManager;
14+
15+
$tm = new ThreadManager();
16+
17+
$tm->parentFunc = function () {
18+
register_shutdown_function(function () {
19+
echo "shutdown\n";
20+
});
21+
Assert::eq(Thread::info()['thread_num'], 1);
22+
$thread = new Thread(__FILE__, 'child');
23+
usleep(100000);
24+
echo "main thread\n";
25+
Assert::eq(Thread::info()['thread_num'], 2);
26+
$thread->detach();
27+
};
28+
29+
$tm->childFunc = function () {
30+
echo "child thread\n";
31+
sleep(1000);
32+
exit(0);
33+
};
34+
35+
$tm->run();
36+
?>
37+
--EXPECTF--
38+
child thread
39+
main thread
40+
shutdown
41+
[%s] WARNING php_swoole_thread_rshutdown(): Fatal Error: 2 active threads are running, cannot exit safely.

0 commit comments

Comments
 (0)