I am using a blocking socket to accept connection. I rarely get this error which makes it hard to debug. The accept returns with EAGAIN error. How can that be for a blocking socket?
+2
A:
If the socket has a receive timeout set (with the SO_RCVTIMEO
socket option), then accept
will return EAGAIN
when the timeout expires.
This code will demonstrate it (and also let you investigate the effect of delivering a signal):
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/time.h>
#define TESTEXIT(s, f) if (s < 0) { perror(f); exit(1); }
void handler(int x)
{
return;
}
int main()
{
int s;
int r;
struct sockaddr_in sin;
socklen_t sin_len = sizeof sin;
struct timeval timeo = { .tv_sec = 5, .tv_usec = 0 };
signal(SIGUSR1, handler);
s = socket(PF_INET, SOCK_STREAM, 0);
TESTEXIT(s, "socket");
r = listen(s, 10);
TESTEXIT(r, "listen");
r = setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof timeo);
TESTEXIT(r, "setsockopt");
r = accept(s, (struct sockaddr *)&sin, &sin_len);
TESTEXIT(r, "accept");
return 0;
}
caf
2009-12-16 22:04:57
I think the relevant bit of kernel code can be found in net/ipv4/inet_connection_sock.c, in the function inet_csk_wait_for_connect().It's not entirely clear to me what can happen there but it looks like the function can return -EAGAIN if the wait is interrupted by anything other than a signal (which does return -EINTR).I don't know what other causes for wakeups there are besided the receive timeout you mentioned though.
Kristof Provost
2009-12-16 22:24:18