Since it seems that I can't find a solution to my original problem, I tried to do a little workaround. I'm simply trying to set a timeout to the connect()
call of my TCP Socket.
connect()
to be blocking but not until the usual 75 seconds timeout, I want to define my own.select()
which worked for the timeout but I couldn't get a connection (that was my initial problem as described here ).So now I found another way to deal with it: just do a blocking connect()
call but interrupt it with an alarm like this :
signal(SIGALRM, connect_alarm);
int secs = 5;
alarm(secs);
if (connect(m_Socket, (struct sockaddr *)&addr, sizeof(addr)) < 0 )
{
if ( errno == EINTR )
{
debug_printf("Timeout");
m_connectionStatus = STATUS_CLOSED;
return ERR_TIMEOUT;
}
else
{
debug_printf("Other Err");
m_connectionStatus = STATUS_CLOSED;
return ERR_NET_SOCKET;
}
}
with
static void connect_alarm(int signo)
{
debug_printf("SignalHandler");
return;
}
This is the solution I found on the Internet in a thread here on stackoverflow. If I use this code the program starts the timer and then goes into the connect()
call. After the 5 seconds the signal handler is fired (as seen on the console with the printf()
), but after that the program still remains within the connect()
function for 75 seconds. Actually every description says that the connect_alarm()
should interrupt the connect()
function but it seems it doesn't in my case. Is there any way to get the desired result for my problem?
signal
is a massively under-specified interface and should be avoided in new code. On some versions of Linux, I believe it provides "BSD semantics", which means (among other things) that providing SA_RESTART
by default.
Use sigaction
instead, do not specify SA_RESTART
, and you should be good to go.
...
Well, except for the general fragility and unavoidable race conditions, that is. connect
will return EINTR
for any signal, not just SIGALARM
. More troublesome, if the system happens to be under heavy load, it could take more than 5 seconds between the call to alarm
and the call to connect
, in which case you will miss the signal and block in connect
forever.
Your earlier attempt, using non-blocking sockets with connect
and select
, was a much better idea. I would suggest debugging that.