Page 1 of 1

Random ERRNO 9 (EBADF) on recv() or send()

Posted: Tue Jul 14, 2020 9:03 am
by sharkx
The context
Several nodes running as APs connecting to each other in a tree-like network; all nodes run the same code.

There's a pretty basic TCP server that listens for small packets of data; the server is running a 'classic' soccket() -> bind() -> listen() -> select() - accept() -> recv() scenario, using the recv() in a separate task; the socket file descriptor is released immediately after the recv completes.

The server processes an average of 2 packets per second. When a packet is received, it is relayed to some of the stations that are connected to the module, or to the 'parent' node depending on data.

The problem
Every now and then, the recv() or send() calls return error code 9, EBADF, and I can't seem to figure out why ...
Sometimes everything goes well for minutes, then there's a 'burst' of EBADFs; sometimes there's one EBADF every minute ort so... there doesn't seem to be a particular pattern.

Any help about debugging this issue is appeciated.
Thanks.

Re: Random ERRNO 9 (EBADF) on recv() or send()

Posted: Wed Jul 15, 2020 2:43 pm
by ESP_Sprite
Are you sure you're handling your file descriptors correctly? No race conditions there?

Re: Random ERRNO 9 (EBADF) on recv() or send()

Posted: Thu Jul 16, 2020 5:01 am
by sharkx
Well... That's part of the problem; there none that I could find. Stripping all error handling and other minor stuff, here's how it's done (in a simplified, c-like language)

Code: Select all

function serverTask() {
    server_socket = socket();
    bind(server_socket);
    listen(server_socket);
    while (1) {
        if (select(server_socket) >= 0) {
            server_accept = accept(server_socket);
            createTask(recvTask, server_accept);
        }
    }
}

function recvTask(server_accept) {
    if (recv(server_accept) > 0) {
        process(received_data);
    }
    closeSocket(server_accept)
}
It's pretty basic. This is how it's supposed to be done, right ?

There is some synchronization done in the processing section, but it does not involve the socket; besides, the socket fd is sent to the task and should become available for another operation after the close occurrs in the recvTask.