The g_poll() function returns -1 "on error or if the call was interrupted". (See: https://developer.gnome.org/glib/2.28/glib-The-Main-Event-Loop.html#g-poll).
If g_poll returns -1 how do I determine if this was because the call was interrupted vs. if there was an error?
If it was an error, how do I determine the cause of the error? Is it sufficient to look at errno?
Yes. Check errno if g_poll() returns -1. The documentation also says
gpoll() polls fds, as with the poll() system call, but portably.
On systems that don't have poll(), it is emulated using select().
i.e. g_poll() uses poll() and select() internally.
Hence, check the various scenarios that errno is set to various values by poll() and select()
Related
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.
I'm programming with socket which is in blocking mode, I have a question about send method.
In the man page of send method, it says:
[EINTR] A signal interrupts the system call before any data is transmitted.
It means if a signal interrupts the system call before any data is transmitted, the send would return -1 and errno would be set to EINTR.
My question is that if a part of data has been transmitted when a signal interrupts the system call, what will return. It seems that it shouldn't return -1 because it has send some data. I think it will return the number of data has been transmitted which means send method in the blocking mode may return less number of data than you passed as third parameter.
ssize_t send(int socket, const void *buffer, size_t length, int flags);
The other answers are pretty clear, but after reading some of your comments, I would like to add some further information.
First of all, you got the idea behind EINTR wrong. Getting interrupted by a signal in a syscall is not to be perceived as an error. The rationale behind EINTR in slow syscalls (slow syscalls are those that can block forever, like open(2) on some file types - terminal devices for example - accept(2), read(2) and write(2) on some devices - sockets included - etc.) is that if your program was blocked in a syscall and a signal was caught (while still blocked), then it is very likely (but not mandatory) that the signal handler changed state in your program and things are different, so the call returns prematurely with EINTR to give you a chance of doing anything that you might want to do. It is not an error like EINVAL or EBADF or other "real" errors - it's just the way the kernel tells you that a signal was caught.
If you don't want to do anything, then either set the SA_RESTART flag on the sa_flags field of struct sigaction when setting up the signal handler (which causes the syscall to be automatically restarted), or explicitly call send(2) again when it returns -1 with errno set to EINTR.
The bottom line is, there isn't an inherent limitation on the kernel that forces it to return to userspace when signals are caught. Instead, EINTR is just a convenient behavior that developers might find useful.
If the kernel was in the midst of transmitting data and a signal was raised, it's no big deal: if data is being transmitted, the syscall is doing progress. The kernel is in process context executing a syscall in behalf of the program that called it, so technically the process is not sleeping anymore. If a signal arrives, it will be pending until the kernel decides that it's time to deliver it to the process - most likely, this happens once send(2) returns.
The documentation is clear.
RETURN VALUE
On success, these calls return the number of bytes sent. On error, -1 is returned, and errno is set appropriately.
[...]
EINTR A signal occurred before any data was transmitted;
send() either returns
the number of bytes sent
or -1
If -1 is returned the reason is indicated via the value of errno.
If errno equals EINTR a signal interupted send() while no data had been received so far.
From this info above one can safely conclude that if data had been received the send() function would not return -1, not matter whether a signal was received or not.
[EINTR] A signal interrupts the system call before any data is transmitted.
This means that if send() start transmitting data, it won't be interrupted by any signals. So, transmission will block the receiving of signal until it finishes. The situation that send() may return less bytes of data than you passed as third parameter is usually due to the network problems, such as packets lost.
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.
Some system calls can be restarted transparently by the Kernel if the SA_RESTART flag is used when installing the signal handler, according to man signal(7):
If a blocked call to one of the following interfaces is interrupted
by a signal handler, then the call will be automatically restarted
after the signal
handler returns if the SA_RESTART flag was used; otherwise the call will fail with the error EINTR:
Then it mentions some system calls that can (and can not) be restarted, but does not mention close() in either places, how would I know if close(), or any other function, is restartable or not ? does POSIX specify it or is it a Linux-specific behaviour ? where can I find more info ?
close is a rather special case. Not only is it not restartable on Linux; when close returns with EINTR on Linux, it has actually already succeeded, and making another call to close will fail with EBADF in single-threaded processes and cause extremely dangerous file-descriptor races in multi-threaded processes.
As of the published POSIX 2008, this behavior is permitted:
If close() is interrupted by a signal that is to be caught, it shall return -1 with errno set to [EINTR] and the state of fildes is unspecified.
This issue was raised with the Austin Group (as Issue #529) and it was resolved to revise the specification such that returning with EINTR means the file descriptor is still open; this is contrary to the current Linux behavior. If the file descriptor has already been closed at the time the signal is handled, the close function is now required to return with EINPROGRESS instead of EINTR. This can be fixed in userspace on Linux, and there is an open glibc bug report, #14627 for it, but as of this writing it has not received any response.
This issue also has serious implications for POSIX thread cancellation, the side effects of which are specified in terms of the side effects upon returning with EINTR. There is a related issue on the Austin Group tracker, Issue #614.
As per POSIX.1-2008, the SA_RESTART flag applies to all interruptible functions (all function which are documented to fail with EINTR):
SA_RESTART
This flag affects the behavior of interruptible functions; that is, those specified to fail with errno set to [EINTR]. If set, and a function specified as interruptible is interrupted by this signal, the function shall restart and shall not fail with [EINTR] unless otherwise specified. If an interruptible function which uses a timeout is restarted, the duration of the timeout following the restart is set to an unspecified value that does not exceed the original timeout value. If the flag is not set, interruptible functions interrupted by this signal shall fail with errno set to [EINTR].
That is, the list of functions which are not restarted is Linux-specific (and probably counts as a bug).
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.