【问题标题】:Linux kernel bug? Create new socket defaults to non blockingLinux内核错误?创建新套接字默认为非阻塞
【发布时间】:2019-10-24 06:10:00
【问题描述】:

对于简单的 TCP 客户端代码,connect 调用返回 EINPROGRESS 而没有任何非阻塞设置指令,而 send 调用返回 EAGAIN。以下是该进程的 strace 记录:

// ...
getsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "\1\0\0\0\0\0\0\0 \241\7\0\0\0\0\0", [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, "\1\0\0\0\0\0\0\0 \241\7\0\0\0\0\0", 16) = 0
setsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "\1\0\0\0\0\0\0\0 \241\7\0\0\0\0\0", 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\0\0\0\206\0\0\0\0\213\1\203\1\0\0\0", 16, 0, NULL, 0) = -1 EAGAIN (Resource temporarily unavailable)
getsockopt(4, SOL_SOCKET, SO_SNDTIMEO, "\1\0\0\0\0\0\0\0 \241\7\0\0\0\0\0", [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。有什么我遗漏的东西还是一个错误?

【问题讨论】:

  • 有一个发送超时设置,在Linux中也会影响connect()。
  • 可以,但即使连接超时也不应该返回 EINPROGRESS。
  • 不要乱用 SO_LINGER。大多数情况下这是一个错误。

标签: linux sockets tcp nonblocking


【解决方案1】:

来自 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 结果。

【讨论】:

    猜你喜欢
    • 2013-06-03
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    • 2010-11-04
    • 2010-09-15
    • 2010-10-31
    • 2013-10-15
    • 1970-01-01
    相关资源
    最近更新 更多