Skip to content

Commit d14fcea

Browse files
committed
Fixed GH-5671
1 parent 4a85999 commit d14fcea

File tree

4 files changed

+128
-2
lines changed

4 files changed

+128
-2
lines changed

src/server/reactor_thread.cc

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ static int ReactorThread_onWrite(Reactor *reactor, Event *ev);
3333
static int ReactorThread_onPacketReceived(Reactor *reactor, Event *event);
3434
static int ReactorThread_onClose(Reactor *reactor, Event *event);
3535
static void ReactorThread_resume_data_receiving(Timer *timer, TimerNode *tnode);
36+
static void ReactorThread_heartbeat_check(Timer *timer, TimerNode *tnode);
3637

3738
#ifdef SW_USE_OPENSSL
3839
static inline ReturnCode ReactorThread_verify_ssl_state(Reactor *reactor, ListenPort *port, Socket *_socket) {
@@ -652,6 +653,27 @@ static int ReactorThread_onWrite(Reactor *reactor, Event *ev) {
652653
return SW_OK;
653654
}
654655

656+
static void ReactorThread_heartbeat_check(Timer *timer, TimerNode *tnode) {
657+
double now = microtime();
658+
Reactor *reactor = (Reactor *) tnode->data;
659+
Server *serv = (Server *) reactor->ptr;
660+
ReactorThread *thread = serv->get_thread(reactor->id);
661+
662+
serv->foreach_connection([=](Connection *conn) {
663+
SessionId session_id = conn->session_id;
664+
if (session_id <= 0) {
665+
return;
666+
}
667+
if (conn->reactor_id != reactor->id) {
668+
return;
669+
}
670+
if (serv->is_healthy_connection(now, conn)) {
671+
return;
672+
}
673+
thread->close_connection(reactor, session_id);
674+
});
675+
}
676+
655677
/**
656678
* [master]
657679
*/
@@ -705,7 +727,12 @@ int Server::start_reactor_threads() {
705727
* heartbeat thread
706728
*/
707729
if (heartbeat_check_interval >= 1) {
708-
start_heartbeat_thread();
730+
if (single_thread) {
731+
heartbeat_timer = swoole_timer_add(
732+
(long) (heartbeat_check_interval * 1000), true, ReactorThread_heartbeat_check, reactor);
733+
} else {
734+
start_heartbeat_thread();
735+
}
709736
}
710737

711738
return start_master_thread(reactor);
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
swoole_server/single_thread: heartbeat
3+
--SKIPIF--
4+
<?php require __DIR__ . '/../../include/skipif.inc';
5+
?>
6+
--FILE--
7+
<?php
8+
require __DIR__ . '/../../include/bootstrap.php';
9+
10+
$pm = new SwooleTest\ProcessManager;
11+
$pm->parentFunc = function ($pid) use ($pm) {
12+
Assert::isEmpty(@file_get_contents('http://127.0.0.1:' . $pm->getFreePort() . '/'));
13+
$pm->kill();
14+
};
15+
16+
$pm->childFunc = function () use ($pm) {
17+
$http = new Swoole\Http\Server('0.0.0.0', $pm->getFreePort(), SWOOLE_PROCESS);
18+
$http->set([
19+
'single_thread' => true,
20+
'worker_num' => 1,
21+
'heartbeat_idle_time' => 1,
22+
'heartbeat_check_interval' => 1,
23+
]);
24+
$http->on('WorkerStart', function (Swoole\Http\Server $serv) use ($pm) {
25+
$pm->wakeup();
26+
});
27+
$http->on('Request', function ($request, $response) use ($http) {
28+
sleep(3);
29+
Assert::false($response->end('hello'));
30+
Assert::eq($http->getLastError(), SWOOLE_ERROR_SESSION_NOT_EXIST);
31+
});
32+
$http->start();
33+
};
34+
35+
$pm->childFirst();
36+
$pm->run();
37+
?>
38+
--EXPECT--

tests/swoole_server/single_thread/large_packet.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
swoole_server/length: package_length_func
2+
swoole_server/single_thread: large packet
33
--SKIPIF--
44
<?php require __DIR__ . '/../../include/skipif.inc';
55
?>
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
--TEST--
2+
swoole_server/single_thread: package_length_func
3+
--SKIPIF--
4+
<?php require __DIR__ . '/../../include/skipif.inc';
5+
?>
6+
--FILE--
7+
<?php
8+
require __DIR__ . '/../../include/bootstrap.php';
9+
10+
$pm = new SwooleTest\ProcessManager;
11+
$pm->parentFunc = function ($pid) use ($pm) {
12+
$url = 'http://127.0.0.1:' . $pm->getFreePort() . '/';
13+
$filePath = tempnam('/tmp', 'swoole_test_');
14+
$rdata = random_bytes(1024 * 1024);
15+
file_put_contents($filePath, $rdata);
16+
$ch = curl_init();
17+
18+
curl_setopt($ch, CURLOPT_URL, $url);
19+
curl_setopt($ch, CURLOPT_POST, true);
20+
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
21+
curl_setopt($ch, CURLOPT_HTTPHEADER, [
22+
'Accept: text/html',
23+
'Content-Type: multipart/form-data'
24+
]);
25+
curl_setopt($ch, CURLOPT_POSTFIELDS, [
26+
'file' => new CURLFile($filePath, 'text/html')
27+
]);
28+
$response = curl_exec($ch);
29+
if (curl_errno($ch)) {
30+
echo 'ERROR: ' . curl_error($ch);
31+
} else {
32+
Assert::eq($response, md5($rdata));
33+
}
34+
curl_close($ch);
35+
unlink($filePath);
36+
$pm->kill();
37+
};
38+
39+
$pm->childFunc = function () use ($pm) {
40+
$http = new Swoole\Http\Server('0.0.0.0', $pm->getFreePort(), SWOOLE_PROCESS);
41+
$http->set([
42+
'single_thread' => true,
43+
'worker_num' => 1,
44+
'user' => 'www-data',
45+
'group' => 'www-data',
46+
'heartbeat_idle_time' => 600,
47+
'heartbeat_check_interval' => 30,
48+
]);
49+
$http->on('WorkerStart', function (Swoole\Http\Server $serv) use ($pm) {
50+
$pm->wakeup();
51+
});
52+
$http->on('Request', function ($request, $response) {
53+
$response->end(md5_file($request->files['file']['tmp_name']));
54+
});
55+
$http->start();
56+
};
57+
58+
$pm->childFirst();
59+
$pm->run();
60+
?>
61+
--EXPECT--

0 commit comments

Comments
 (0)