Skip to content

Commit 741e352

Browse files
authored
Refactor AsyncRequest, fix #5547 (#5550)
* Refactor AsyncRequest, fix #5547 * fix * add tests * optimize code * optimize tests * optimize code 2
1 parent 3016130 commit 741e352

File tree

14 files changed

+118
-77
lines changed

14 files changed

+118
-77
lines changed

core-tests/src/network/dns.cpp

+1-8
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,7 @@ TEST(dns, cancel) {
7474
}
7575

7676
TEST(dns, getaddrinfo) {
77-
char buf[1024] = {};
78-
swoole::network::GetaddrinfoRequest req = {};
79-
req.hostname = "www.baidu.com";
80-
req.family = AF_INET;
81-
req.socktype = SOCK_STREAM;
82-
req.protocol = 0;
83-
req.service = nullptr;
84-
req.result = buf;
77+
swoole::GetaddrinfoRequest req("www.baidu.com", AF_INET, SOCK_STREAM, 0, "");
8578
ASSERT_EQ(swoole::network::getaddrinfo(&req), 0);
8679
ASSERT_GT(req.count, 0);
8780

include/swoole_async.h

+34-5
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ enum AsyncFlag {
3939
SW_AIO_EOF = 1u << 2,
4040
};
4141

42+
struct AsyncRequest {
43+
virtual ~AsyncRequest() = default;
44+
};
45+
4246
struct AsyncEvent {
4347
size_t task_id;
4448
#ifdef SW_USE_IOURING
@@ -49,7 +53,7 @@ struct AsyncEvent {
4953
/**
5054
* input & output
5155
*/
52-
void *data;
56+
std::shared_ptr<AsyncRequest> data;
5357
#ifdef SW_USE_IOURING
5458
const char *pathname;
5559
const char *pathname2;
@@ -81,22 +85,47 @@ struct AsyncEvent {
8185
}
8286
};
8387

84-
struct GethostbynameRequest {
85-
const char *name;
88+
struct GethostbynameRequest : public AsyncRequest {
89+
std::string name;
8690
int family;
8791
char *addr;
8892
size_t addr_len;
8993

90-
GethostbynameRequest(const char *_name, int _family) : name(_name), family(_family) {
94+
GethostbynameRequest(std::string _name, int _family) : name(std::move(_name)), family(_family) {
9195
addr_len = _family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN;
9296
addr = new char[addr_len];
9397
}
9498

95-
~GethostbynameRequest() {
99+
~GethostbynameRequest() override {
96100
delete[] addr;
97101
}
98102
};
99103

104+
struct GetaddrinfoRequest : public AsyncRequest {
105+
std::string hostname;
106+
std::string service;
107+
int family;
108+
int socktype;
109+
int protocol;
110+
int error;
111+
std::vector<struct sockaddr_in6> results;
112+
int count;
113+
114+
void parse_result(std::vector<std::string> &retval);
115+
116+
GetaddrinfoRequest(std::string _hostname, int _family, int _socktype, int _protocol, std::string _service)
117+
: hostname(std::move(_hostname)),
118+
service(std::move(_service)) {
119+
family =_family;
120+
socktype =_socktype;
121+
protocol =_protocol;
122+
count = 0;
123+
error = 0;
124+
}
125+
126+
~GetaddrinfoRequest() override = default;
127+
};
128+
100129
class AsyncThreads {
101130
public:
102131
size_t task_num = 0;

include/swoole_socket.h

+2-13
Original file line numberDiff line numberDiff line change
@@ -64,20 +64,9 @@ enum {
6464
};
6565

6666
namespace swoole {
67-
namespace network {
67+
struct GetaddrinfoRequest;
6868

69-
struct GetaddrinfoRequest {
70-
const char *hostname;
71-
const char *service;
72-
int family;
73-
int socktype;
74-
int protocol;
75-
int error;
76-
void *result;
77-
int count;
78-
79-
void parse_result(std::vector<std::string> &retval);
80-
};
69+
namespace network {
8170

8271
struct SendfileTask {
8372
off_t offset;

include/swoole_util.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,7 @@ class BitMap {
153153
}
154154

155155
void clear() {
156-
memset(array_, 0, get_array_size(n_bits_));
156+
memset(array_, 0, sizeof(uint64_t) * get_array_size(n_bits_));
157157
}
158158

159159
void set(size_t i) {

scripts/make.sh

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
1-
#!/bin/sh -e
1+
#!/bin/sh
22
__CURRENT_DIR__=$(cd "$(dirname "$0")";pwd)
33
__DIR__=$(cd "$(dirname "${__CURRENT_DIR__}")";pwd)
4+
__HAVE_ZTS__=$(php -v|grep ZTS)
5+
46
COMPILE_PARAMS="--enable-openssl \
57
--enable-sockets \
68
--enable-mysqlnd \
79
--enable-swoole-curl \
810
--enable-cares \
9-
--enable-swoole-thread \
1011
--enable-swoole-pgsql \
1112
--with-swoole-odbc=unixODBC,/usr \
1213
--enable-swoole-sqlite"
1314

15+
if [ -n "$__HAVE_ZTS__" ]; then
16+
COMPILE_PARAMS="$COMPILE_PARAMS --enable-swoole-thread"
17+
fi
1418

1519
if [ "$(uname | grep -i darwin)"x != ""x ]; then
1620
CPU_COUNT="$(sysctl -n machdep.cpu.core_count)"

src/coroutine/system.cc

+7-17
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ ssize_t System::write_file(const char *file, char *buf, size_t length, bool lock
137137

138138
std::string gethostbyname_impl_with_async(const std::string &hostname, int domain, double timeout) {
139139
AsyncEvent ev{};
140-
GethostbynameRequest dns_request(hostname.c_str(), domain);
141-
ev.data = &dns_request;
140+
auto req = new GethostbynameRequest(hostname, domain);
141+
ev.data = std::shared_ptr<AsyncRequest>(req);
142142
ev.retval = 1;
143143

144144
coroutine::async(async::handler_gethostbyname, ev, timeout);
@@ -150,7 +150,7 @@ std::string gethostbyname_impl_with_async(const std::string &hostname, int domai
150150
swoole_set_last_error(ev.error);
151151
return "";
152152
} else {
153-
std::string addr(dns_request.addr);
153+
std::string addr(req->addr);
154154
return addr;
155155
}
156156
}
@@ -199,30 +199,20 @@ std::vector<std::string> System::getaddrinfo(
199199
assert(family == AF_INET || family == AF_INET6);
200200

201201
AsyncEvent ev{};
202-
network::GetaddrinfoRequest req{};
203-
204-
ev.data = &req;
205-
206-
struct sockaddr_in6 result_buffer[SW_DNS_HOST_BUFFER_SIZE];
207-
208-
req.hostname = hostname.c_str();
209-
req.family = family;
210-
req.socktype = socktype;
211-
req.protocol = protocol;
212-
req.service = service.empty() ? nullptr : service.c_str();
213-
req.result = result_buffer;
202+
auto req = new GetaddrinfoRequest(hostname, family, socktype, protocol, service);
203+
ev.data = std::shared_ptr<AsyncRequest>(req);
214204

215205
coroutine::async(async::handler_getaddrinfo, ev, timeout);
216206

217207
std::vector<std::string> retval;
218208

219-
if (ev.retval == -1 || req.error != 0) {
209+
if (ev.retval == -1 || req->error != 0) {
220210
if (ev.error == SW_ERROR_AIO_TIMEOUT) {
221211
ev.error = SW_ERROR_DNSLOOKUP_RESOLVE_TIMEOUT;
222212
}
223213
swoole_set_last_error(ev.error);
224214
} else {
225-
req.parse_result(retval);
215+
req->parse_result(retval);
226216
}
227217

228218
return retval;

src/network/client.cc

+4-10
Original file line numberDiff line numberDiff line change
@@ -615,14 +615,13 @@ static int Client_tcp_connect_async(Client *cli, const char *host, int port, dou
615615

616616
if (cli->wait_dns) {
617617
AsyncEvent ev{};
618-
auto dns_request = new GethostbynameRequest(cli->server_host, cli->_sock_domain);
619-
ev.data = dns_request;
618+
auto req = new GethostbynameRequest(cli->server_host, cli->_sock_domain);
619+
ev.data = std::shared_ptr<AsyncRequest>(req);
620620
ev.object = cli;
621621
ev.handler = async::handler_gethostbyname;
622622
ev.callback = Client_onResolveCompleted;
623623

624624
if (swoole::async::dispatch(&ev) == nullptr) {
625-
delete dns_request;
626625
return SW_ERR;
627626
} else {
628627
return SW_OK;
@@ -1112,17 +1111,13 @@ static void Client_onTimeout(Timer *timer, TimerNode *tnode) {
11121111
}
11131112

11141113
static void Client_onResolveCompleted(AsyncEvent *event) {
1115-
auto dns_request = (GethostbynameRequest *) event->data;
1116-
if (event->canceled) {
1117-
delete dns_request;
1118-
return;
1119-
}
1114+
GethostbynameRequest *req = dynamic_cast<GethostbynameRequest *>(event->data.get());
11201115

11211116
Client *cli = (Client *) event->object;
11221117
cli->wait_dns = 0;
11231118

11241119
if (event->error == 0) {
1125-
Client_tcp_connect_async(cli, dns_request->addr, cli->server_port, cli->timeout, 1);
1120+
Client_tcp_connect_async(cli, req->addr, cli->server_port, cli->timeout, 1);
11261121
} else {
11271122
swoole_set_last_error(SW_ERROR_DNSLOOKUP_RESOLVE_FAILED);
11281123
cli->socket->removed = 1;
@@ -1131,7 +1126,6 @@ static void Client_onResolveCompleted(AsyncEvent *event) {
11311126
cli->onError(cli);
11321127
}
11331128
}
1134-
delete dns_request;
11351129
}
11361130

11371131
static int Client_onWrite(Reactor *reactor, Event *event) {

src/network/dns.cc

+16-13
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ std::vector<std::string> dns_lookup_impl_with_socket(const char *domain, int fam
344344
temp = &packet[steps];
345345
j = 0;
346346
while (*temp != 0) {
347-
if ((uchar)(*temp) == 0xc0) {
347+
if ((uchar) (*temp) == 0xc0) {
348348
++temp;
349349
temp = &packet[(uint8_t) *temp];
350350
} else {
@@ -373,7 +373,7 @@ std::vector<std::string> dns_lookup_impl_with_socket(const char *domain, int fam
373373
temp = &packet[steps];
374374
j = 0;
375375
while (*temp != 0) {
376-
if ((uchar)(*temp) == 0xc0) {
376+
if ((uchar) (*temp) == 0xc0) {
377377
++temp;
378378
temp = &packet[(uint8_t) *temp];
379379
} else {
@@ -767,36 +767,40 @@ int getaddrinfo(GetaddrinfoRequest *req) {
767767
hints.ai_socktype = req->socktype;
768768
hints.ai_protocol = req->protocol;
769769

770-
int ret = ::getaddrinfo(req->hostname, req->service, &hints, &result);
770+
int ret = ::getaddrinfo(req->hostname.c_str(), req->service.c_str(), &hints, &result);
771771
if (ret != 0) {
772772
req->error = ret;
773773
return SW_ERR;
774774
}
775775

776-
void *buffer = req->result;
777776
int i = 0;
778-
for (ptr = result; ptr != nullptr; ptr = ptr->ai_next) {
777+
for (ptr = result; ptr != nullptr; ptr = ptr->ai_next, i++) {
778+
}
779+
req->count = SW_MIN(i, SW_DNS_HOST_BUFFER_SIZE);
780+
req->results.resize(req->count);
781+
782+
for (ptr = result, i = 0; ptr != nullptr; ptr = ptr->ai_next, i++) {
779783
switch (ptr->ai_family) {
780784
case AF_INET:
781-
memcpy((char *) buffer + (i * sizeof(struct sockaddr_in)), ptr->ai_addr, sizeof(struct sockaddr_in));
785+
memcpy(&req->results[i], ptr->ai_addr, sizeof(struct sockaddr_in));
782786
break;
783787
case AF_INET6:
784-
memcpy((char *) buffer + (i * sizeof(struct sockaddr_in6)), ptr->ai_addr, sizeof(struct sockaddr_in6));
788+
memcpy(&req->results[i], ptr->ai_addr, sizeof(struct sockaddr_in6));
785789
break;
786790
default:
787791
swoole_warning("unknown socket family[%d]", ptr->ai_family);
788792
break;
789793
}
790-
i++;
791794
if (i == SW_DNS_HOST_BUFFER_SIZE) {
792795
break;
793796
}
794797
}
795798
::freeaddrinfo(result);
796799
req->error = 0;
797-
req->count = i;
800+
798801
return SW_OK;
799802
}
803+
} // namespace network
800804

801805
void GetaddrinfoRequest::parse_result(std::vector<std::string> &retval) {
802806
struct sockaddr_in *addr_v4;
@@ -805,18 +809,17 @@ void GetaddrinfoRequest::parse_result(std::vector<std::string> &retval) {
805809
char tmp[INET6_ADDRSTRLEN];
806810
const char *r;
807811

808-
for (int i = 0; i < count; i++) {
812+
for (auto &addr : results) {
809813
if (family == AF_INET) {
810-
addr_v4 = (struct sockaddr_in *) ((char *) result + (i * sizeof(struct sockaddr_in)));
814+
addr_v4 = (struct sockaddr_in *) &addr;
811815
r = inet_ntop(AF_INET, (const void *) &addr_v4->sin_addr, tmp, sizeof(tmp));
812816
} else {
813-
addr_v6 = (struct sockaddr_in6 *) ((char *) result + (i * sizeof(struct sockaddr_in6)));
817+
addr_v6 = (struct sockaddr_in6 *) &addr;
814818
r = inet_ntop(AF_INET6, (const void *) &addr_v6->sin6_addr, tmp, sizeof(tmp));
815819
}
816820
if (r) {
817821
retval.push_back(tmp);
818822
}
819823
}
820824
}
821-
} // namespace network
822825
} // namespace swoole

src/os/base.cc

+5-5
Original file line numberDiff line numberDiff line change
@@ -93,14 +93,14 @@ namespace async {
9393

9494
void handler_gethostbyname(AsyncEvent *event) {
9595
char addr[INET6_ADDRSTRLEN];
96-
auto request = (GethostbynameRequest *) event->data;
97-
int ret = network::gethostbyname(request->family, request->name, addr);
98-
sw_memset_zero(request->addr, request->addr_len);
96+
auto req = dynamic_cast<GethostbynameRequest *>(event->data.get());
97+
int ret = network::gethostbyname(req->family, req->name.c_str(), addr);
98+
sw_memset_zero(req->addr, req->addr_len);
9999

100100
if (ret < 0) {
101101
event->error = SW_ERROR_DNSLOOKUP_RESOLVE_FAILED;
102102
} else {
103-
if (inet_ntop(request->family, addr, request->addr, request->addr_len) == nullptr) {
103+
if (inet_ntop(req->family, addr, req->addr, req->addr_len) == nullptr) {
104104
ret = -1;
105105
event->error = SW_ERROR_BAD_IPV6_ADDRESS;
106106
} else {
@@ -112,7 +112,7 @@ void handler_gethostbyname(AsyncEvent *event) {
112112
}
113113

114114
void handler_getaddrinfo(AsyncEvent *event) {
115-
network::GetaddrinfoRequest *req = (network::GetaddrinfoRequest *) event->data;
115+
auto req = dynamic_cast<GetaddrinfoRequest *>(event->data.get());
116116
event->retval = network::getaddrinfo(req);
117117
event->error = req->error;
118118
}

tests/include/functions.php

+7
Original file line numberDiff line numberDiff line change
@@ -865,3 +865,10 @@ function get_thread_name(): string
865865
{
866866
return trim(file_get_contents('/proc/' . posix_getpid() . '/task/' . \Swoole\Thread::getNativeId() . '/comm'));
867867
}
868+
869+
function mkdir_if_not_exists(string $string): void
870+
{
871+
if (!is_dir($string)) {
872+
mkdir($string, 0777, true);
873+
}
874+
}

tests/include/skipif.inc

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ function swoole_color(string $content, int $color): string
4545
function skip(string $reason, bool $is_skip = true, int $color = SWOOLE_COLOR_YELLOW)
4646
{
4747
if ($is_skip) {
48-
exit('skip ' . swoole_color($reason, $color));
48+
exit('skip ' . swoole_color($reason, $color) . "\n");
4949
}
5050
}
5151

tests/swoole_coroutine_system/getaddrinfo.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ skip_if_offline();
77
--FILE--
88
<?php
99
require __DIR__ . '/../include/bootstrap.php';
10-
go(function () {
10+
Co\run(function () {
1111
$ip_list = Swoole\Coroutine\System::getaddrinfo('www.baidu.com', AF_INET);
1212
Assert::assert(!empty($ip_list) and is_array($ip_list));
1313
foreach ($ip_list as $ip) {

0 commit comments

Comments
 (0)