简体   繁体   中英

C Bad file descriptor issue when using accept() on sockets that is on different threads

What you are trying to do:

Hello, I'm rewriting a old legacy custom http server used on a website.

What's the issue:

When accept is called, Can't accept client: bad file descriptor error will be outputted to the terminal even though code looks correct.

What you tried:

  • changed orders of stuff
  • I decided that my boilerplate has hidden errors can't be seen so I copied boilerplate from a random website on the internet but Im not satisfied with that so I returned back to my own code.

Code:

#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>

// This version of software is licensed under public domain feel free to use for any purpose
typedef struct{
    char* http_path;
    void (*function);
} location;
unsigned short server_count = 0;

/*
 * typedef struct is bad practice especially by linux convention which i try to
 * follow but for some reason program will compile or fail randomly and typedef
 * struct fixes it for some reason
*/
typedef struct{
    unsigned char running;
    unsigned id;
    unsigned locationCount;
    location* locations;
    unsigned port;    
} http_server_t;
http_server_t* servers;

char nServer(unsigned short port) {
    server_count++;
    char status = server_count;
    // The warning happens here can be disregarded
    if(server_count == 1) {
        status = (servers = malloc(sizeof(servers)*server_count));
    }else{
        status = (realloc(servers, sizeof(servers)*server_count));
    }
    if(!status){
        return -1;
    }
    servers[server_count].port = port;
    servers[server_count].running = 1;
    servers[server_count].locations = sizeof(servers[server_count].locations)*servers[server_count].locationCount+1;
    return server_count;

    
}
typedef struct __attribute__((packed)) {
    unsigned sock;
    struct sockaddr* addr;
    struct sockaddr_in inf;
} serverHandlerData;

void serveClient() {

}
void socketHandle(void* data) {
    // lazy to properly name these stuff
    // FIXME: Refactor the code here

    
   
    
    serverHandlerData *fixed = data;
    unsigned sock = fixed->sock; struct sockaddr* addr = fixed->addr;
    struct sockaddr_in in = fixed->inf;

    if(bind(sock, (struct sockaddr *)&in, sizeof(struct sockaddr))) {
        perror("Can't bind");
        return;
    } 

    if((listen(sock, 0)) < 0) {
        perror("Can't listen the socket");
        return;
    }        



    for(;;) {
        int csock;
        struct sockaddr_in caddr;
        if((csock = accept(csock, (struct sockaddr*)&caddr, (socklen_t)sizeof(struct sockaddr))) < 0) {
            perror("Can't accept client");
            return;
        }

        unsigned char* buffer = malloc(100);
        read(csock, buffer, 100);
        printf(buffer);
        close(csock);
    }
    

}
void iServers() {
    for(unsigned long x = 1; x < server_count; x++) {
        struct sockaddr_in addr;
        unsigned char status = 0;
        unsigned int sock = 0;
        if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
            perror("Socket can't be made due a error");
            return;
        }
        printf("%d", servers[x].port);

        memset(&addr, 0, sizeof(addr));
        // ipv4
        


        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = htonl(INADDR_ANY);
        addr.sin_port = htons(servers[x].port);
        /*if((setsockopt(sock, (struct sockaddr*)&addr, SO_REUSEADDR,
                     SO_BROADCAST, (struct socklen_t*)sizeof(SO_BROADCAST))) < 0){
                        perror("Failure while setting socket options");
                        return;
        }      */  
        serverHandlerData s;
        s.sock = sock;
        s.addr = (struct sockaddr*)&addr;
        s.inf = addr;


        pthread_t serverHandle;

        pthread_create(&serverHandle, NULL, socketHandle, &s);
        pthread_join(serverHandle, NULL);
    }
}

unsigned char running = 1;

void ctrlCHandler(){
    running = 0;
}
int main() {
    nServer(4080);
    // FIXME: Second server never gets toggled on
    nServer(1010);

    //nServer(80);

    iServers();
    return 0;
}

Minimal example? I do not know what exactly triggers the error so I can't create a minimal reproducable example.

IMHO, the problem is that you have requested

listen(sock, 0); /* BAD */

as this sets the incoming backlog queue to 0 entries, dissalowing connection establishment. The normal call should be (to behave as it used to)

listen(sock, 5); /* OK */

that allows up to 5 connect requests before starting to reject connections.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM