c++socketssignalsalarm

Connect Timeout with Alarm()


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.

  1. I want the connect() to be blocking but not until the usual 75 seconds timeout, I want to define my own.
  2. I have already tried 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?


Solution

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