Can socket() fail with EINPROGRESS - c

Is it possible for the socket() function to fail with EINPROGRESS in Linux? Note that I am specifically asking about socket(), not connect() or others.
POSIX does not list EINPROGRESS as a possible error code. However the manpage for socket() in Linux says:
Other errors may be generated by the underlying protocol modules.
Is there any circumstances in which this call can actually fail with EINPROGRESS?

EINPROGRESS means the operation is now in progress. It would block because of an external reason : wait for a remote action or a local device.
socket() is only creating an entry in the memory of the system : there is no reason to wait for any remote action or any device.
But if it were able to return EINPROGRESS, you would have nothing to wait for.
With file handles and socket handles, you can use select() in order to wait for the system to be ready. But if the socket() itself does not return anything, you have nothing to wait on.
I see no reason for socket() to return EIPROGRESS but it would be a bad idea anyway.

Maybe not the answer you were looking for:
You'll have to check the corresponding Linux kernel source code (kernel/net/socket.c) throughly to be 100% sure. Glancing through the code, it doesn't look like EINPROGRESS is returned anywhere. However, there are runtime dependent calls in there, so its difficult to say just from static code analysis.

Related

listen called on socket more than once -- expected behavior?

I noticed something odd while working with a simple C-based server
program on my Linux (4.10.3) system. I accidentally ended up calling
listen() twice on a socket (from the server process) I had
called bind() on earlier. I noticed that both the listen calls
succeeded without any errors. In fact, it doesn't seem to matter how many
calls to listen I make, all calls to listen succeed.
I was expecting all the calls to listen after the first one to fail
with EADDRINUSE. Am I missing something? Linux/POSIX man pages don't
seem to say anything about this. I did find one reference about
this behavior on the following web-page:
https://www.mkssoftware.com/docs/man3/listen.3.asp
An application may call listen() more than once on the same socket.
This has the effect of updating the current backlog for the listening
socket. Should there be more pending connections than the new backlog
value, the excess pending connections are reset and dropped.
It's unclear to me if this also applies to Linux. And so my question is:
what happens when listen is called on the same socket more than once from
the same process? (Apparently there are no visible side-effects in user space,
but does the Linux kernel do something special in kernel space?)
Thanks.
The Linux kernel adjusts the backlog queue length using the new backlog value, but only for future connection requests. It does not discard any pending connections already in the queue.
Second and subsequent calls to listen() have no other effect, and will not fail unless the socket is of the wrong type (not SOCK_STREAM), or is in the wrong state (already connected to a specific peer, or is already in the process of being closed).

SO_ERROR vs. errno

For getting socket syscall (like recv) error, which is better (at performance level) ?
Use the plain old errno
Or use SO_ERROR as getsockopt() optname ?
I think errno (defined to __error() on my system) is faster because it's not a system call. Am I right ?
The advantages of SO_ERROR are : automatic error reset after getting, and we are sure that the error only concerns our socket. It's safer.
Which one do you think is better ? Is there a really difference of performance between the two ?
Quoting Dan Bernstein:
Situation: You set up a non-blocking socket and do a connect() that returns -1/EINPROGRESS or -1/EWOULDBLOCK. You select() the socket for writability. This returns as soon as the connection succeeds or fails. (Exception: Under some old versions of Ultrix, select() wouldn't notice failure before the 75-second timeout.)
Question: What do you do after select() returns writability? Did the connection fail? If so, how did it fail?
If the connection failed, the reason is hidden away inside something called so_error in the socket. Modern systems let you see so_error with getsockopt(,,SO_ERROR,,) ...
He goes on to discuss the fact that getsockopt(,,SO_ERROR,,) is a modern invention that doesn't work on old systems, and how to get the error code on such systems. But you probably don't need to worry about that if you're programming for a Unix/Linux system released in the last 15 years.
The Linux man page for connect describes the same usage of SO_ERROR.
So, if you're performing asynchronous operations on sockets, you may need to use SO_ERROR. In any other case, just use errno.
Quoting Unix Network Programming:
If so_error is nonzero when the process calls read and there is no
data to return, read returns –1 with errno set to the value of so_error
(p. 516 of TCPv2). The value of so_error is then reset to 0. If there
is data queued for the socket, that data is returned by read instead
of the error condition. If so_error is nonzero when the process calls
write, –1 is returned with errno set to the value of so_error (p. 495
of TCPv2) and so_error is reset to 0.
So, errno is the better choice, unless you want to get error immediately before the data is fully fetched.

Is it possible (and safe) to make an accepting socket non-blocking?

I'm looking for a way to interrupt an accept() call on a blocking socket. Using signals is not an option, as this is meant to be in a library and I don't want to clutter the user signals. Using select() is another option, buf for various reason it's not very appealing in my case.
What would work well, if possible, is to set the socket to non-blocking mode (using fcntl() and O_NONBLOCK) from another thread, while the socket is blocked on an accept() call. The expected behaviour is that the accept() call will return with EAGAIN or EWOULDBLOCK in errno.
Would it indeed work like that? Is it safe? Portable?
If you know about the applicability of this method to Windows (where you need to use WSAIoctl() and FONBIO), I'm also interested.
No idea about Windows, but the behavior you want is guaranteed by POSIX:
If the listen queue is empty of connection requests and O_NONBLOCK is not set on the file descriptor for the socket, accept() shall block until a connection is present. If the listen() queue is empty of connection requests and O_NONBLOCK is set on the file descriptor for the socket, accept() shall fail and set errno to [EAGAIN] or [EWOULDBLOCK].
Source: http://pubs.opengroup.org/onlinepubs/9699919799/functions/accept.html
Also, select or poll can be used to check for incoming connections by polling for the listening socket in the reading set.
In the question, You are saying that you do not want to use select (or poll or epoll) which are the best ways for IO multiplexing. I would recommend you using one another thread just for listening sockets while this is a bad idea!

Read signaled by select(), but recv() returns no data and signal EAGAIN on non-blocking sockets

I have got signaled socket for read from select(), but then no data arrived by recv call(), instead it returns -1 with errno==EAGAIN.
I can grant that no other thread touch the socket.
I think that this behavior is not correct. If an subsequent close from other side occurs, I can expect return value 0 (graceful close) or other error code from recv, but not EAGAIN, because it means by my opinion that an data will arrive in the future.
I have found some previous thread about the problem here but without solution.
This behavior happens to me on Ubuntu Linux Oneric, or other last Linux distros, then info from link posted here
That it will be fixed in kernel is not true for 3.0.0 kernel or latest 2.6.x
Does anybody have an idea why it happens and how to avoid this unwanted behavior?
Select() reporting a socket as readable does not mean that there is something to read; it implies that a read will not block. The read could return -1 or 0, but it would not block.
UPDATE:
After select returns readable: if read() returns -1, check errno.
EAGAIN/EWOULDBLOCK and EINTR are the values to be treated specially: mostly by reissuing the read(), but you might trust on the select loop returning readable the next time around.
If there are multiple threads involved, things may get more difficult.
I'm getting the same problem but with epoll. I noticed, that it happens whenever the system is reusing the FD numbers of the sockets that are already closed.
After some research, I've noticed that this behavior is caused by closing the sockets while epolling on them. Try to avoid running select on a socket while closing it - that may help.

reentrant function read()

I have found a server by select(), which I want to receive from some clients.
But I find that the server will get blocked in read() by gdb.
So I thought of solving it by adding a SIGALRM, but
when a timeout occurs, it's still blocked in read().
This happens because, system calls are automatically restarted, the read()
is not interrupted when the SIGALRM signal handler returns.
Is this interpretation correct?
The usual solution to this problem is to use SOCK_NONBLOCK to socket(2) or O_NONBLOCK to fcntl(2)'s F_SETFL command. Once the socket is marked non-blocking, it'll never block when you try to read from it, and you won't need to try to straddle the divide between blocking or non-blocking. Are you sure select(2) set the filedescriptor? The select(2) manpage does describe one reason why you see what you're seeing, but it doesn't seem likely:
Under Linux, select() may report a socket file descriptor as
"ready for reading", while nevertheless a subsequent read
blocks. This could for example happen when data has arrived
but upon examination has wrong checksum and is discarded.
There may be other circumstances in which a file descriptor is
spuriously reported as ready. Thus it may be safer to use
O_NONBLOCK on sockets that should not block.
If you really just want to prevent the automatic restart, look into SA_RESTART in sigaction(2) to prevent restartable system calls from restarting.

Resources