zlg
zlg

Reputation: 13

C socket() creation fails in the loop, too many open files

I am implementing a client-server TCP socket application. Client is on an OpenWRT Linux router (C based) and writes some data on the socket repeatedly and in a loop at some frequency rate. The Server is on a Linux Ubuntu machine (C/C++ based) and reads data in a loop according to data arrival speed.

Problem: Running the Server and then Client, server keeps reading new data. Both sides work well until the number of data deliveries (# of connections) reaches 1013. After that, the Client stuck at socket(AF_INET,SOCK_STREAM,0) with socket creation failed...: Too many open files. Apparently, the number of open fd approaches ulimit -n = 1024 on client.

I put the snippets of the code which shows the loop structures for Server.cpp and Client.c:

Server.c:

//    TCP Socket creation stuff over here (work as they should):
//    int sock_ = socket() / bind() / listen()

while (1)
{
        socklen_t sizeOfserv_addr = sizeof(serv_addr_);
        fd_set set;
        struct timeval timeout;
        int connfd_;
        FD_ZERO(&set);
        FD_SET(sock_, &set);
        timeout.tv_sec = 10;
        timeout.tv_usec = 0;
        int rv_ = select(sock_ + 1, &set, NULL, NULL, &timeout);
        if(rv_ == -1){
            perror("select");
            return 1;
        }
        else if(rv_ == 0){
            printf("Client disconnected.."); /* a timeout occured */
            close (connfd_);
            close (sock_);
        }
        else{
            connfd_ = accept (sock_,(struct sockaddr*)&serv_addr_,(socklen_t*)&sizeOfserv_addr);
            if (connfd_ >= 0) {
                int ret = read (connfd_, &payload, sizeof(payload));    /* some payload */
                if (ret > 0)
                     printf("Received %d bytes !\n", ret);
                close (connfd_);  /* Keep parent socket open (sock_) */
            }else{
                printf("Server acccept failed..\n");
                close (connfd_);
                close (stcp.sock_);
                return 0;
            }
        }
}

Client.cpp:

while (payload_exist)               /* assuming payload_exist is true */
{
        struct sockaddr_in servaddr;
        int sock;
        if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
            perror("socket creation failed...\n");

        int one = 1;
        int idletime = 2;
        setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &one, sizeof(one));
        setsockopt(sock, IPPROTO_TCP, TCP_KEEPIDLE, &idletime, sizeof(idletime));
        setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));

        bzero(&servaddr, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_addr.s_addr = inet_addr("192.168.100.12");
        servaddr.sin_port = htons(PORT);  /* some PORT */
        if (connect (sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) != 0){
            perror("connect failed...");
            return 1;
        }
        write(sock, (struct sockaddr*)&payload, sizeof(payload));  /* some new payload */
        shutdown(sock,SHUT_WR);

        bool serverOff = false;
        while (!serverOff){
             if(read(sock, &res, sizeof(res)) < 0){
                 serverOff = true;
                 close(sock); 
             }
        }
}

NOTE: payload is 800 bytes and always gets fully transmitted per one write action. Having both codes defined under int main(), the client keeps creating sockets and sending data, on the other side, server receives all and would automatically close() and leave if client terminates, due to using select(). If I don't terminate the Client, however, by checking some print logs, it is evident that Server successfully receives 1013 payloads before client crashes with socket creation failed...: Too many open files.

Update:

Following the point mentioned by Steffen Ullrich, it turned out that, the client socket fd has no leak, and the existence of a second fd in the original loop (which was left open) was making the ulimit exceed the limit.

Upvotes: 0

Views: 1169

Answers (1)

Steffen Ullrich
Steffen Ullrich

Reputation: 123280

        if(read(sock, &res, sizeof(res)) < 0){
             serverOff = true;
             close(sock);   /********* Not actually closing sock *********/
        }

Your check for end of connection is wrong. read returns 0 if the other side has shut down the connection and <0 only on error.

    if (sock = socket(AF_INET, SOCK_STREAM, 0) == -1)
        perror("socket creation failed...\n");

Given the precedence of operators in C this basically says:

    sock = ( socket(AF_INET, SOCK_STREAM, 0) == -1) )
    if (sock) ...

Assuming that socket(...) will not return an error but a file descriptor (i.e. >=0) the comparison will be false and thus this essentially says sock = 0 while leaking a file descriptor if the fd returned by socket was >0.

Upvotes: 4

Related Questions