1

I am trying to handle a socket connection from a different process while asynchronously handling SIGALRMs from the alarm function. To simulate and test this, I'm using the Linux commands nc 127.0.0.1 [port] and kill -14 $(myprocess). However, when running the kill command followed by the nc command, select returns instantaneously in an infinite loop like fashion. The C code which contains the select statement is below.

int main() {
    int port = 4555;
    int master_sockfd;
    bind_and_listen(&master_sockfd, port);
    signal(SIGALRM, handle_alarm);

    for (;;) {
        fd_set readfds;
        int max_fd = master_sockfd;
        FD_ZERO(&readfds);
        FD_SET(master_sockfd, &readfds);

        printf("waiting for master_sockfd to be set\n");

        int activity = select(max_fd + 1, &readfds, NULL, NULL, NULL);

        if ((activity < 0) && (errno != EINTR)) {
            perror("select() ");
            exit(EXIT_FAILURE);

        } else if (errno == EINTR) {
            perror("select() ");
            if (FD_ISSET(master_sockfd, &readfds)) {
                printf("Why is sockfd ready for I/O if select was interrupted with a signal?\n");
            }
            continue;

        } else if (FD_ISSET(master_sockfd, &readfds)) {
            printf("Reading from socket\n");
            // handle client
        }
    }
    return 0;
}

void handle_alarm() {
    printf("handling alarm\n");
}

Then, upon executing kill -14 $(myprocess); nc 127.0.0.1 4555 The output is as follows:

select() : Interrupted system call
Why is sockfd ready for I/O if select was interrupted with a signal?
waiting for master_sockfd to be set
select() : Interrupted system call
Why is sockfd ready for I/O if select was interrupted with a signal?
waiting for master_sockfd to be set
select() : Interrupted system call
Why is sockfd ready for I/O if select was interrupted with a signal?
waiting for master_sockfd to be set
.
.
.

Which prints out infinitely.

Why would this be happening?

New contributor
snailsuperperson is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
2

When select() fails, you cannot rely on the values of the parameters from it. They might reflect something, nothing, or some intermediary state. In your case, it looks like select() never updated the fdsets at all; so they reflect your initial value. This makes sense; it was interrupted so it never wrote back its results.

Your error detection isn't quite right either, it should be:

if (activity < 0) {
    /* select failed */
    if (errno != EINTR) {
        /* handle non-eintr cases */
    } else {
        /* handle eintr case */
    }
} else {
    /*select succeeded */
}

Your Answer

snailsuperperson is a new contributor. Be nice, and check out our Code of Conduct.

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.