Search code examples
linuxsocketstcpnonblocking

Linux kernel bug? Create new socket defaults to non blocking


For a simple TCP Client code, the connect call returns EINPROGRESS without any nonblocking setup directive, and the send call returns EAGAIN. Here is the strace record for the process:

// ...
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

I'm running 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. Is there something I'm missing or it is a bug?


Solution

  • From the socket(7) manual page

       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.
    

    so by setting a timeout you may get an EAGAIN/EINPROGRESS result if the timeout expires.