Sergey Alikin
Sergey Alikin

Reputation: 161

select() returns that socket is ready when SIGALRM

I'm sorry if this question has already sounded - could not find ... So I have timer:

bzero(&rtc_act, sizeof(struct sigaction));
rtc_act.sa_handler = &rtc_handler;
sigaction(SIGALRM, &rtc_act, NULL);

rtc_timer.it_interval.tv_sec = SETTIMER_INTERVAL;
rtc_timer.it_interval.tv_usec = 0;
rtc_timer.it_value.tv_sec = SETTIMER_VALUE;
rtc_timer.it_value.tv_usec = 0;

if (setitimer(ITIMER_REAL, &rtc_timer, NULL))
{
    printf(MSG_ERR_SETTIMER_FAIL);
    retval = RETURN_ERR_SETTIMER;
} /* if (setitimer(ITIMER_REAL, &rtc_timer, NULL)) */

Also i have blocked socket:

if ((modbus_socket = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
    retval = RETURN_ERR_SOCKET_OPEN;
    perror(MSG_ERR_OPEN_SOCKET);
    return retval;
} /* if (modbus_socket = socket(AF_INET, SOCK_STREAM, 0) < 0) */

setsockopt(modbus_socket, SOL_SOCKET, SO_REUSEADDR, (const void*)&optval , sizeof(unsigned int));

bzero((char*)&serv_addr, sizeof(serv_addr));

serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons((unsigned short)ZK91_TCP_PORT_NUMBER);

if (bind(modbus_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
{
    perror(MSG_ERR_BIND_SOCKET);
    retval = RETURN_ERR_SOCKET_OPEN;
    return retval;
} /* if (bind(modbus_socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) */

if (listen(modbus_socket, TCP_CLIENTS_COUNT) < 0)
{
    perror(MSG_ERR_LISTEN_SOCKET);
    retval = RETURN_ERR_SOCKET_LISTEN;
    return retval;
} /* if (listen(parentfd, TCP_CLIENTS_COUNT) < 0) */

When i try to use select()

    FD_ZERO(&fds);
    FD_SET(modbus_socket, &fds);
    FD_SET(can_file, &fds);
    FD_SET(modbus_file, &fds);

    select(modbus_file + 1, &fds, NULL, NULL, &tv);

I get the activation select() in a few seconds, although the actual data were not available.

If you try to handle this "connection":

new_socket = accept (modbus_socket, (struct sockaddr *) & client_addr, & client_len);

then the program crashes giving the screen 10 characters from then the some memory region:

net is coming (my message)

������硨���L�

uclinux#

If I do not initialize the timer, then everything works correctly, but on a timer I can not refuse.

In what could be the reason?

Thank you.

Upvotes: 0

Views: 869

Answers (2)

trojanfoe
trojanfoe

Reputation: 122381

You need to check errno if select() fails and ignore it for SIGALRM interruptions.

Something like:

for (;;) {
    int rv = select(...);
    if (rv < 0) {
        if (errno == EINTR)
            continue;    // Was a signal
        else
            // A real error occurred
    } else {
        // Handle event
    }
}

Upvotes: 1

unwind
unwind

Reputation: 399703

You must check, after select() returns, why it returns. You can't just assume that it's saying "socket ready for reading", without checking.

The checking is done using the FD_ISSET() macro, to see if the socket file descriptor is still in the ready for reading set.

If select() is returning due to being interrupted, it will also set errno to EINTR, and return -1. Since it normally returns the number of set descriptors in the three input sets, you should check the return value too. No need to start calling FD_ISSET() unless select() has returned a value greater than 0.

Upvotes: 0

Related Questions