Linux Server Connector - Bad File Descriptor

I have a problem with a server socket under Linux. For some reason, the server socket unknown to me goes to zero, and I get a Bad file descriptor error in a select call that is waiting for an incoming connection. This problem always occurs when I close an unconnected socket connection in another thread. This happens on embedded Linux with the 2.6.36 kernel.

Does anyone know why this will happen? Is it normal that the server socket might just disappear, resulting in a Bad file descriptor ?

change Another socket code implements a VNC server and works in a completely different thread. The only thing that is especially important in this other code is the use of setjmp/longjmp , but this should not be a problem.

The code that creates the server socket is as follows:

 int server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(1234); const int optionval = 1; setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, &optionval, sizeof(optionval)); if (bind(server_socket, (struct sockaddr *) &saddr, sizeof(saddr)) < 0) { perror("bind"); return 0; } if (listen(server_socket, 1) < 0) { perror("listen"); return 0; } 

I am waiting for an incoming connection using the following code:

 static int WaitForConnection(int server_socket, struct timeval *timeout) { fd_set read_fds; FD_ZERO(&read_fds); int max_sd = server_socket; FD_SET(server_socket, &read_fds); // This select will result in 'EBADFD' in the error case. // Even though the server socket was not closed with 'close'. int res = select(max_sd + 1, &read_fds, NULL, NULL, timeout); if (res > 0) { struct sockaddr_in caddr; socklen_t clen = sizeof(caddr); return accept(server_socket, (struct sockaddr *) &caddr, &clen); } return -1; } 

edit When a problem occurs, I am currently just restarting the server, but I don’t understand why the server identifier should suddenly become an invalid file descriptor:

 int error = 0; socklen_t len = sizeof (error); int retval = getsockopt (server_socket, SOL_SOCKET, SO_ERROR, &error, &len ); if (retval < 0) { close(server_socket); goto server_start; } 
+4
source share
4 answers

Sockets (file descriptors) usually suffer from the same control problems as the original pointers in C Whenever you close a socket, be sure to assign -1 variable that stores the value of the descriptor:

 close(socket); socket = -1; 

As you would point to a C pointer

 free(buffer); buffer = NULL; 

If you forgot to do this, you can later close the socket twice, since you would free() memory twice if it was a pointer.

Another problem may be related to what people usually forget: file descriptors on UNIX start at 0 . If somewhere in the code there is

 struct FooData { int foo; int socket; ... } // Either FooData my_data_1 = {0}; // Or FooData my_data_2; memset(&my_data_2, 0, sizeof(my_data_2)); 

In both cases, my_data_1 and my_data_2 have a valid handle value ( socket ). And later, the part of the code responsible for freeing the FooData structure can blindly close() describe this handle, which you happen to use to listen on the server socket ( 0 ).

+4
source

You do not distinguish between two cases of errors in your code; both can fail with select or accept . I assume that you just have a timeout, and this choice returns 0 .

  • print retval and errno in the else branch
  • examine accept return value separately
  • make sure errno is reset to 0 before each of the system calls
+1
source

1- close the socket:

 close(sockfd); 

2- clear the socket file descriptor of the selected set:

 FD_CLR(sockfd,&master); //opposite of FD_SET 
0
source

On Linux, when you create a connection and it closes, you need to wait a while before establishing a new connection. Like Linux, the socket does not release port no. as soon as you close the socket.

OR

Reuse the socket, then you need to specify the file descriptor.

-3
source

All Articles