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

sharkx
Posts: 5
Joined: Fri Feb 28, 2020 3:27 pm

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

Postby sharkx » Tue Jul 14, 2020 9:03 am

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.

ESP_Sprite
Posts: 9582
Joined: Thu Nov 26, 2015 4:08 am

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

Postby ESP_Sprite » Wed Jul 15, 2020 2:43 pm

Are you sure you're handling your file descriptors correctly? No race conditions there?

sharkx
Posts: 5
Joined: Fri Feb 28, 2020 3:27 pm

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

Postby sharkx » Thu Jul 16, 2020 5:01 am

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.

Who is online

Users browsing this forum: Baidu [Spider], omerfurkan.ipek and 234 guests