Skip to content

Commit 3d8abe6

Browse files
committed
Fix issue of unexpected response timeouts when an HTTP client with long time keep-alive. see https://github.com/swoole/benchmark/blob/master/co_http_client_keepalive.php
1 parent 050293e commit 3d8abe6

File tree

2 files changed

+26
-22
lines changed

2 files changed

+26
-22
lines changed

ext-src/swoole_http_client_coro.cc

+11-8
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ class Client {
9393
#ifdef SW_USE_OPENSSL
9494
uint8_t ssl;
9595
#endif
96-
double connect_timeout = network::Socket::default_connect_timeout;
96+
double connect_timeout = 0;
97+
double response_timeout = 0;
9798
bool defer = false;
9899
bool lowercase_header = true;
99100
bool use_default_port;
@@ -706,10 +707,12 @@ void Client::apply_setting(zval *zset, const bool check_all) {
706707
zval *ztmp;
707708
HashTable *vht = Z_ARRVAL_P(zset);
708709

709-
if (php_swoole_array_get_value(vht, "connect_timeout", ztmp) ||
710-
php_swoole_array_get_value(vht, "timeout", ztmp) /* backward compatibility */) {
710+
if (php_swoole_array_get_value(vht, "connect_timeout", ztmp)) {
711711
connect_timeout = zval_get_double(ztmp);
712712
}
713+
if (php_swoole_array_get_value(vht, "timeout", ztmp)) {
714+
response_timeout = zval_get_double(ztmp);
715+
}
713716
if (php_swoole_array_get_value(vht, "max_retries", ztmp)) {
714717
max_retries = (uint8_t) SW_MIN(zval_get_long(ztmp), UINT8_MAX);
715718
}
@@ -863,11 +866,11 @@ bool Client::connect() {
863866
accept_websocket_compression = false;
864867
#endif
865868

866-
// socket->set_buffer_allocator(&SWOOLE_G(zend_string_allocator));
867-
// connect
868-
socket->set_timeout(connect_timeout, Socket::TIMEOUT_CONNECT);
869+
double _timeout = connect_timeout == 0 ? network::Socket::default_connect_timeout : connect_timeout;
870+
socket->set_timeout(_timeout, Socket::TIMEOUT_CONNECT);
869871
socket->set_resolve_context(&resolve_context_);
870872
socket->set_dtor([this](Socket *_socket) { socket_dtor(); });
873+
// socket->set_buffer_allocator(&SWOOLE_G(zend_string_allocator));
871874

872875
if (!socket->connect(host, port)) {
873876
set_error(socket->errCode, socket->errMsg, ESTATUS_CONNECT_FAILED);
@@ -1425,9 +1428,9 @@ bool Client::recv_response(double timeout) {
14251428
parser.data = this;
14261429

14271430
if (timeout == 0) {
1428-
timeout = socket->get_timeout(Socket::TIMEOUT_READ);
1431+
timeout = response_timeout == 0 ? network::Socket::default_read_timeout : response_timeout;
14291432
}
1430-
Socket::timeout_controller tc(socket, timeout, Socket::TIMEOUT_READ);
1433+
Socket::TimeoutController tc(socket, timeout, Socket::TIMEOUT_READ);
14311434
bool success = false;
14321435
while (true) {
14331436
if (sw_unlikely(tc.has_timedout(Socket::TIMEOUT_READ))) {

include/swoole_coroutine_socket.h

+15-14
Original file line numberDiff line numberDiff line change
@@ -509,8 +509,8 @@ class Socket {
509509

510510
class TimerController {
511511
public:
512-
TimerController(TimerNode **timer_pp, double timeout, Socket *sock, TimerCallback callback)
513-
: timer_pp(timer_pp), timeout(timeout), socket_(sock), callback(callback) {}
512+
TimerController(TimerNode **_timer_pp, double _timeout, Socket *_socket, TimerCallback _callback)
513+
: timer_pp(_timer_pp), timeout(_timeout), socket_(_socket), callback(std::move(_callback)) {}
514514
bool start() {
515515
if (timeout != 0 && !*timer_pp) {
516516
enabled = true;
@@ -542,16 +542,16 @@ class Socket {
542542
public:
543543
class TimeoutSetter {
544544
public:
545-
TimeoutSetter(Socket *socket, double timeout, const enum TimeoutType type)
546-
: socket_(socket), timeout(timeout), type(type) {
547-
if (timeout == 0) {
545+
TimeoutSetter(Socket *socket, double _timeout, const enum TimeoutType _type)
546+
: socket_(socket), timeout(_timeout), type(_type) {
547+
if (_timeout == 0) {
548548
return;
549549
}
550550
for (uint8_t i = 0; i < SW_ARRAY_SIZE(timeout_type_list); i++) {
551-
if (type & timeout_type_list[i]) {
551+
if (_type & timeout_type_list[i]) {
552552
original_timeout[i] = socket->get_timeout(timeout_type_list[i]);
553-
if (timeout != original_timeout[i]) {
554-
socket->set_timeout(timeout, timeout_type_list[i]);
553+
if (_timeout != original_timeout[i]) {
554+
socket->set_timeout(_timeout, timeout_type_list[i]);
555555
}
556556
}
557557
}
@@ -576,12 +576,13 @@ class Socket {
576576
double original_timeout[sizeof(timeout_type_list)] = {};
577577
};
578578

579-
class timeout_controller : public TimeoutSetter {
579+
class TimeoutController : public TimeoutSetter {
580580
public:
581-
timeout_controller(Socket *socket, double timeout, const enum TimeoutType type)
582-
: TimeoutSetter(socket, timeout, type) {}
583-
bool has_timedout(const enum TimeoutType type) {
584-
SW_ASSERT_1BYTE(type);
581+
TimeoutController(Socket *_socket, double _timeout, const enum TimeoutType _type)
582+
: TimeoutSetter(_socket, _timeout, _type) {}
583+
584+
bool has_timedout(const enum TimeoutType _type) {
585+
SW_ASSERT_1BYTE(_type);
585586
if (timeout > 0) {
586587
if (sw_unlikely(startup_time == 0)) {
587588
startup_time = microtime();
@@ -591,7 +592,7 @@ class Socket {
591592
socket_->set_err(ETIMEDOUT);
592593
return true;
593594
}
594-
socket_->set_timeout(timeout - used_time, type);
595+
socket_->set_timeout(timeout - used_time, _type);
595596
}
596597
}
597598
return false;

0 commit comments

Comments
 (0)