mirror of
https://github.com/curl/curl.git
synced 2025-01-12 13:55:11 +08:00
socket: use SOCK_NONBLOCK to eliminate extra system call
Every time function `cf_socket_open()` is called to create a socket, `curlx_nonblock()` is called to make that socket non-blocking. And `curlx_nonblock()` will cost us 1 or 2 system calls (2 for `fcntl()`, 1 for `ioctl()`, etc.), meanwhile, tucking `SOCK_NONBLOCK` and `SOCK_CLOEXEC` into the `type` argument for `socket()` is widely supported across UNIX-like OS: Linux, *BSD, Solaris, etc. With that ability, we can save 1 or 2 system calls on each socket. Another change in this PR is to eliminate the redundant `curlx_nonblock()` call on the socket in `cf_udp_setup_quic()` as that socket created by `cf_socket_open()` is already non-blocking. Ref: https://man7.org/linux/man-pages/man2/socket.2.html https://man.freebsd.org/cgi/man.cgi?socket(2) https://man.dragonflybsd.org/?command=socket§ion=2 https://man.netbsd.org/socket.2 https://man.openbsd.org/socket https://docs.oracle.com/cd/E88353_01/html/E37843/socket-3c.html https://illumos.org/man/3SOCKET/socket ... Closes #13855
This commit is contained in:
parent
97e5e37cc8
commit
3392f0f97e
@ -1016,7 +1016,20 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
|
||||
(void)data;
|
||||
DEBUGASSERT(ctx->sock == CURL_SOCKET_BAD);
|
||||
ctx->started_at = Curl_now();
|
||||
#ifdef SOCK_NONBLOCK
|
||||
/* Don't tuck SOCK_NONBLOCK into socktype when opensocket callback is set
|
||||
* because we wouldn't know how socketype is about to be used in the
|
||||
* callback, SOCK_NONBLOCK might get factored out before calling socket().
|
||||
*/
|
||||
if(!data->set.fopensocket)
|
||||
ctx->addr.socktype |= SOCK_NONBLOCK;
|
||||
#endif
|
||||
result = socket_open(data, &ctx->addr, &ctx->sock);
|
||||
#ifdef SOCK_NONBLOCK
|
||||
/* Restore the socktype after the socket is created. */
|
||||
if(!data->set.fopensocket)
|
||||
ctx->addr.socktype &= ~SOCK_NONBLOCK;
|
||||
#endif
|
||||
if(result)
|
||||
goto out;
|
||||
|
||||
@ -1087,8 +1100,14 @@ static CURLcode cf_socket_open(struct Curl_cfilter *cf,
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SOCK_NONBLOCK
|
||||
/* set socket non-blocking */
|
||||
(void)curlx_nonblock(ctx->sock, TRUE);
|
||||
#else
|
||||
if(data->set.fopensocket)
|
||||
/* set socket non-blocking */
|
||||
(void)curlx_nonblock(ctx->sock, TRUE);
|
||||
#endif
|
||||
ctx->sock_connected = (ctx->addr.socktype != SOCK_DGRAM);
|
||||
out:
|
||||
if(result) {
|
||||
@ -1681,7 +1700,7 @@ out:
|
||||
}
|
||||
|
||||
static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data)
|
||||
struct Curl_easy *data)
|
||||
{
|
||||
struct cf_socket_ctx *ctx = cf->ctx;
|
||||
int rc;
|
||||
@ -1707,7 +1726,11 @@ static CURLcode cf_udp_setup_quic(struct Curl_cfilter *cf,
|
||||
ctx->sock, ctx->ip.local_ip, ctx->ip.local_port,
|
||||
ctx->ip.remote_ip, ctx->ip.remote_port);
|
||||
|
||||
(void)curlx_nonblock(ctx->sock, TRUE);
|
||||
/* Currently, cf->ctx->sock is always non-blocking because the only
|
||||
* caller to cf_udp_setup_quic() is cf_udp_connect() that passes the
|
||||
* non-blocking socket created by cf_socket_open() to it. Thus, we
|
||||
* don't need to call curlx_nonblock() in cf_udp_setup_quic() anymore.
|
||||
*/
|
||||
switch(ctx->addr.family) {
|
||||
#if defined(__linux__) && defined(IP_MTU_DISCOVER)
|
||||
case AF_INET: {
|
||||
|
Loading…
Reference in New Issue
Block a user