Jump to content
  • Advertisement
Sign in to follow this  
FMDGames

Linux Server Keeps Freezing

This topic is 4320 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a custom built Linux Server which utilizes lua for scripting. I have seen issues where the server will freeze for up to 5 minutes, then all the pending messages are processed. I have no idea what the problem is. For the connections, im using the SELECT function so i can multiplex between the users which is based on the beej guide. The server still accepts connections (as in you can connect, but you get no data and the server sends no data to you). Using top, the server shows no evidence of CPU hogging, and other programs appear to operate fine. I can't see the lua functions that I've written to cause the problem as they work all the time there isn't pauses. Is it a requirement i need to empty the lua stack myself? The server dist is Fedora Core. Any ideas what could be causing this? Regards. -----------------------------------------------
/*
** selectserver.c -- a cheezy multiperson chat server
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 9034   // port we're listening on

int main(void)
{
    fd_set master;   // master file descriptor list
    fd_set read_fds; // temp file descriptor list for select()
    struct sockaddr_in myaddr;     // server address
    struct sockaddr_in remoteaddr; // client address
    int fdmax;        // maximum file descriptor number
    int listener;     // listening socket descriptor
    int newfd;        // newly accept()ed socket descriptor
    char buf[256];    // buffer for client data
    int nbytes;
    int yes=1;        // for setsockopt() SO_REUSEADDR, below
    socklen_t addrlen;
    int i, j;

    FD_ZERO(&master);    // clear the master and temp sets
    FD_ZERO(&read_fds);

    // get the listener
    if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
        perror("socket");
        exit(1);
    }

    // lose the pesky "address already in use" error message
    if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
                                                        sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }

    // bind
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = INADDR_ANY;
    myaddr.sin_port = htons(PORT);
    memset(&(myaddr.sin_zero), '\0', 8);
    if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
        perror("bind");
        exit(1);
    }

    // listen
    if (listen(listener, 10) == -1) {
        perror("listen");
        exit(1);
    }

    // add the listener to the master set
    FD_SET(listener, &master);

    // keep track of the biggest file descriptor
    fdmax = listener; // so far, it's this one

    // main loop
    for(;;) {
        read_fds = master; // copy it
        if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
            perror("select");
            exit(1);
        }

        // run through the existing connections looking for data to read
        for(i = 0; i <= fdmax; i++) {
            if (FD_ISSET(i, &read_fds)) { // we got one!!
                if (i == listener) {
                    // handle new connections
                    addrlen = sizeof(remoteaddr);
                    if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr,
                                                               &addrlen)) == -1) { 
                        perror("accept");
                    } else {
                        FD_SET(newfd, &master); // add to master set
                        if (newfd > fdmax) {    // keep track of the maximum
                            fdmax = newfd;
                        }
                        printf("selectserver: new connection from %s on "
                            "socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd);
                    }
                } else {
                    // handle data from a client
                    if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
                        // got error or connection closed by client
                        if (nbytes == 0) {
                            // connection closed
                            printf("selectserver: socket %d hung up\n", i);
                        } else {
                            perror("recv");
                        }
                        close(i); // bye!
                        FD_CLR(i, &master); // remove from master set
                    } else {
                        // we got some data from a client
                        for(j = 0; j <= fdmax; j++) {
                            // send to everyone!
                            if (FD_ISSET(j, &master)) {
                                // except the listener and ourselves
                                if (j != listener && j != i) {
                                    if (send(j, buf, nbytes, 0) == -1) {
                                        perror("send");
                                    }
                                }
                            }
                        }
                    }
                } // it's SO UGLY!
            }
        }
    }
    
    return 0;
}

Share this post


Link to post
Share on other sites
Advertisement
It may be that your sockets are blocking and it's blocking in send().

In any case, you need to get a debugger and learn how to use it; this will make it easy to see what's going on.

You may also find the output from "netstat" helpful, e.g. if a lot of bytes are in the send queue of a given socket (hence the buffer is full which blocks your app).

Mark

Share this post


Link to post
Share on other sites
You can also use a send queue in the loop, by polling the third argument of select with the sockets you wish to send info on. In any case, it's just good style to make sure that your sockets are ready before pushing information into them.

Share this post


Link to post
Share on other sites
I've updated the server code and pushed it into released status and now its running. No problems soo far, looking good. Thanks for your help. Will post back if theirs any problems!

=)

Share this post


Link to post
Share on other sites
It appears the server is still suffering from the problem.

I'm now using a fd_set for writing, checking if its set for a particular socket, and sending any waiting data if the socket is ready.

What Now? (The problem appears to be linked to a 56k Modem user)

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!