Linux 内核错误?创建新套接字默认为非阻塞
Linux kernel bug? Create new socket defaults to non blocking
对于简单的 TCP 客户端代码,连接调用 returns EINPROGRESS 没有任何非阻塞设置指令,发送调用 returns EAGAIN。这是该过程的 strace 记录:
// ...
getsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", [16]) = 0
setsockopt(4, SOL_SOCKET, SO_LINGER, {l_onoff=1, l_linger=0}, 8) = 0
close(4) = 0
futex(0x16487b0, FUTEX_WAKE_PRIVATE, 1) = 1
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 4
fcntl(4, F_SETFD, FD_CLOEXEC) = 0
setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_RCVTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", 16) = 0
setsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", 16) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(798), sin_addr=inet_addr("192.168.143.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
setsockopt(4, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
times(NULL) = 1718992611
sendto(4, "\f[=11=][=11=][=11=]6[=11=][=11=][=11=][=11=]33[=11=][=11=][=11=]", 16, 0, NULL, 0) = -1 EAGAIN (Resource temporarily unavailable)
getsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", [16]) = 0
setsockopt(4, SOL_SOCKET, SO_LINGER, {l_onoff=1, l_linger=0}, 8) = 0
close(4) = 0
我是 运行 Ubuntu 18.04: Linux test 4.15.0-65-generic #74-Ubuntu SMP Tue Sep 17 17:06:04 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
。有什么我想念的东西或者它是一个错误吗?
来自 socket(7) 手册页
SO_RCVTIMEO and SO_SNDTIMEO
Specify the receiving or sending timeouts until reporting an error. The argument
is a struct timeval. If an input or output function blocks for this period of
time, and data has been sent or received, the return value of that function will be
the amount of data transferred; if no data has been transferred and the timeout has
been reached, then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or EIN‐
PROGRESS (for connect(2)) just as if the socket was specified to be nonblocking.
If the timeout is set to zero (the default), then the operation will never timeout.
Timeouts only have effect for system calls that perform socket I/O (e.g., read(2),
recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for select(2), poll(2),
epoll_wait(2), and so on.
因此,通过设置超时,如果超时到期,您可能会得到 EAGAIN/EINPROGRESS 结果。
对于简单的 TCP 客户端代码,连接调用 returns EINPROGRESS 没有任何非阻塞设置指令,发送调用 returns EAGAIN。这是该过程的 strace 记录:
// ...
getsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", [16]) = 0
setsockopt(4, SOL_SOCKET, SO_LINGER, {l_onoff=1, l_linger=0}, 8) = 0
close(4) = 0
futex(0x16487b0, FUTEX_WAKE_PRIVATE, 1) = 1
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 4
fcntl(4, F_SETFD, FD_CLOEXEC) = 0
setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_RCVTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", 16) = 0
setsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", 16) = 0
connect(4, {sa_family=AF_INET, sin_port=htons(798), sin_addr=inet_addr("192.168.143.1")}, 16) = -1 EINPROGRESS (Operation now in progress)
setsockopt(4, SOL_SOCKET, SO_KEEPALIVE, [1], 4) = 0
times(NULL) = 1718992611
sendto(4, "\f[=11=][=11=][=11=]6[=11=][=11=][=11=][=11=]33[=11=][=11=][=11=]", 16, 0, NULL, 0) = -1 EAGAIN (Resource temporarily unavailable)
getsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "[=11=][=11=][=11=][=11=][=11=][=11=][=11=] 1[=11=][=11=][=11=][=11=][=11=]", [16]) = 0
setsockopt(4, SOL_SOCKET, SO_LINGER, {l_onoff=1, l_linger=0}, 8) = 0
close(4) = 0
我是 运行 Ubuntu 18.04: Linux test 4.15.0-65-generic #74-Ubuntu SMP Tue Sep 17 17:06:04 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
。有什么我想念的东西或者它是一个错误吗?
来自 socket(7) 手册页
SO_RCVTIMEO and SO_SNDTIMEO Specify the receiving or sending timeouts until reporting an error. The argument is a struct timeval. If an input or output function blocks for this period of time, and data has been sent or received, the return value of that function will be the amount of data transferred; if no data has been transferred and the timeout has been reached, then -1 is returned with errno set to EAGAIN or EWOULDBLOCK, or EIN‐ PROGRESS (for connect(2)) just as if the socket was specified to be nonblocking. If the timeout is set to zero (the default), then the operation will never timeout. Timeouts only have effect for system calls that perform socket I/O (e.g., read(2), recvmsg(2), send(2), sendmsg(2)); timeouts have no effect for select(2), poll(2), epoll_wait(2), and so on.
因此,通过设置超时,如果超时到期,您可能会得到 EAGAIN/EINPROGRESS 结果。