espressif / esp-lwip

Fork of lwIP (https://savannah.nongnu.org/projects/lwip/) with ESP-IDF specific patches
Other
85 stars 129 forks source link

Add SO_EXCEPTION to set/getsockopt() (IDFGH-6195) #35

Closed nonoo closed 2 years ago

nonoo commented 3 years ago

This feature works similarly to RTCS's SO_EXCEPTION. Setting an SO_EXCEPTION value for a socket using setsockopt() breaks out from blocking select() calls and puts the socket into the returned exception fd_set. The exception value can be read using getsockopt(). Reading SO_EXCEPTION with getsockopt() clears the exception.

Example usage:

    fd_set readfds;
    fd_set exceptfds;

    FD_ZERO(&readfds);
    FD_SET(sockfd, &readfds);

    FD_ZERO(&exceptfds);
    FD_SET(sockfd, &exceptfds);

    int res = select(sockfd + 1, &readfds, NULL, &exceptfds, NULL);
    if (res < 0) {
        return -1;
    } else if (res == 0) {
        return 0;
    }

    int exception;
    socklen_t len = sizeof(int);

    if (FD_ISSET(sockfd, &exceptfds)) {
        // Reading the exception value. Note that this also clears the value.
        if (getsockopt(sockfd, SOL_SOCKET, SO_EXCEPTION, (void *)&exception, &len) < 0) {
            return -1;
        }

        printf("select exception %d\n", exception); // This will display the exception value set by setsockopt(sockfd, SOL_SOCKET, SO_EXCEPTION, (void *)&value, sizeof(int));

        ... do something useful here ...
    }

    if (FD_ISSET(sockfd, &readfds)) {
       ... handle read from sockfd in case it has bytes available ...
    }
Alvin1Zhang commented 3 years ago

Thanks for your contribution.

david-cermak commented 2 years ago

Hi @nonoo

Thanks for implementing this useful feature. I would however suggest posting it to the lwip upstream: https://savannah.nongnu.org/patch/?group=lwip We generally try to accept only the bugfixes and updates necessary for essential esp-lwip operation with IDF. More so lately, as you can guess from other active issues and PRs, we're trying hard to converge to the upstream rather than diverge from it.

Please note, that IDF has a solution for this usecase already, using VFS component and event-fds, if we wanted to notify and unblock a select() with custom events:

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/storage/vfs.html#event-fds

nonoo commented 2 years ago

Thanks for the info! I didn't know about event-fds. I'll convert my app to use those.