RE: poll with timeout 0 in main loop




i attached the code but did not make thru, here is the server code:

GMTCPServer *tcp_server_new(const Configurations *p_configurations)
{
    GMTCPServer *new_server;
    GError *error = NULL;
    int fd;


    // create a new tcp server object
    new_server = g_new(GMTCPServer,1);

    // get the configurations reference
    new_server->configurations = p_configurations;
    // create the context for this thread
    new_server->context = g_main_context_new();

    // initialize the list of clients
    new_server->clients_list = g_ptr_array_new_with_free_func((void*)gm_connection_destroy);

    // create the server socket
    fd = tcp_server_listerner_new(new_server->configurations,&error);
    if(fd < 0)
    {
        g_error("Could not create listener, server creation aborted: %s",error->message);
        g_error_free(error);
        return NULL;
    }

    // create the GIOChannel for the server socket
    new_server->socket = g_io_channel_unix_new(fd);
    // set the encoding safe to read binary data on the server GIOChannel
    g_io_channel_set_encoding(new_server->socket,NULL,NULL);

    // create a source for connection events on the server socket
    new_server->event_source = 
g_io_create_watch(new_server->socket,G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL);
    // set the callback function to handle connection events
    
g_source_set_callback(new_server->event_source,(GSourceFunc)tcp_server_handle_connection_events,new_server,NULL);
    // attach the server socket connection event source to the server context
    g_source_attach(new_server->event_source,new_server->context);

    // create the callback event source
    new_server->callback_source = async_callback_new();
    // attach the callback event source to the context
    g_source_attach(new_server->callback_source,new_server->context);

    // create the main loop for this thread
    new_server->main_loop = g_main_loop_new(new_server->context,FALSE);

    // the thread will be started later
    new_server->server_thread = NULL;

    return new_server;
}

void tcp_server_destroy(GMTCPServer *p_server)
{
    g_message("Destroying GoMobile server ...");

    // quit the main loop
    g_main_loop_quit(p_server->main_loop);

    // join the server thread
    if(p_server->server_thread != NULL)
    {
        g_thread_join(p_server->server_thread);
    }

    // remove the server socket connection event source from the context
    g_source_destroy(p_server->event_source);

    // remove callback event source from the server context
    g_source_destroy(p_server->callback_source);

    // close and free server socket resources
    g_io_channel_shutdown(p_server->socket,TRUE,NULL);

    // close all client connections
    g_ptr_array_free(p_server->clients_list,TRUE);

    // free resources associated with event source
    g_source_unref(p_server->event_source);

    // free resources associated with the callback event source
    g_source_unref(p_server->callback_source);

    // free the resources in the server socket
    g_io_channel_unref(p_server->socket);

    // destroy the main loop
    g_main_loop_unref(p_server->main_loop);

    // free the context resources
    g_main_context_unref(p_server->context);

    // delete the memory allocated by the tcp object itself
    g_free(p_server);

    g_message("Done");
}

void tcp_server_run(GMTCPServer *p_server)
{
    // run the main loop now
    g_main_loop_run(p_server->main_loop);

    g_thread_exit(NULL);
}

int tcp_server_listerner_new(const Configurations *p_configurations,GError **p_error)
{
    int fd;
    struct sockaddr_in servAddr;
    int set_option = 1;

    // create the socket
    fd = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
    if(fd < 0)
    {
        *p_error = g_error_new(G_IO_CHANNEL_ERROR,G_IO_CHANNEL_ERROR_FAILED,"Could not create server socket: 
%s",strerror(errno));
        return -1;
    }
    // set some options on the socket
    fcntl(fd,F_SETFL,O_NONBLOCK);// set the socket non-blocking
    setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&set_option,sizeof(set_option));// reuse address
    setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,&set_option,sizeof(set_option));// send keep alive messages

    // construct local address structure
    memset(&servAddr,0x00, sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = inet_addr(p_configurations->tcp_server.interface);
    servAddr.sin_port = htons(p_configurations->tcp_server.port);
    // Bind to the local address
    if(bind(fd,(struct sockaddr*)&servAddr,sizeof(servAddr)) < 0)
    {
        *p_error = g_error_new(G_IO_CHANNEL_ERROR,G_IO_CHANNEL_ERROR_FAILED,"Could not bind server socket: 
%s",strerror(errno));
        // close the socket
        close(fd);
        return -1;
    }
    if(listen(fd,10) < 0)
    {
        *p_error = g_error_new(G_IO_CHANNEL_ERROR,G_IO_CHANNEL_ERROR_FAILED,"Could not start listening on the 
server socket: %s",strerror(errno));
        // close the socket
        close(fd);
        return -1;
    }

    return fd;
}

gboolean tcp_server_handle_connection_events(GIOChannel *p_source,GIOCondition p_condition,GMTCPServer 
*p_server)
{
    TCPClientConnection *client = NULL;
    struct sockaddr_in sockaddr;
    socklen_t client_fd_len;
    int client_fd;
//    GError *error = NULL;
    int set_option = 1;

    if(p_condition & (G_IO_IN|G_IO_PRI))
    {
        // accept the connection now
        client_fd_len = sizeof(sockaddr);
        if((client_fd = accept(g_io_channel_unix_get_fd(p_server->socket),(struct 
sockaddr*)&sockaddr,&client_fd_len)) < 0)
        {
            g_error("Could not accept new connection: %s",strerror(errno));
            return TRUE;
        }

        fcntl(client_fd,F_SETFL,O_NONBLOCK);// set the socket non-blocking
        setsockopt(client_fd,SOL_SOCKET,SO_KEEPALIVE,&set_option,sizeof(set_option));// send keep alive 
messages

        g_message("New connection attempt");

        // create a client connection
        client = gm_connection_new(client_fd,p_server);

        // get the address for this client
        if (inet_ntop(AF_INET,&sockaddr.sin_addr.s_addr,client->ip,sizeof(client->ip)) != NULL)
        {
            client->port = ntohs(sockaddr.sin_port);
            g_message("Successfully accepted new client connection from %s:%d",client->ip,client->port);
        }
        else
        {
            client->ip[0] = 0;
            client->port = -1;
            g_message("Successfully accepted new client connection from an unknown location");
        }

        // run the connection thread
        client->connection_thread = 
g_thread_create((GThreadFunc)gm_connection_run,client,TRUE,/*&error*/NULL);
        if(client->connection_thread == NULL)
        {
            g_error("Could not start new connection for client: %s:%d, will end this 
connection",client->ip,client->port);
            gm_connection_destroy(client);
        }
        else
        {
            // push it into the client array
            g_ptr_array_add(p_server->clients_list,client);
            g_message("Successfully started new connection");
        }

        return TRUE;
    }

    // an error happened
    // show an error message and try to get a description from errno
    g_warning("An error occurred on the server socket: %s",strerror(errno));
    return TRUE;
}

gboolean tcp_server_remove_connection(TCPClientConnection *p_client)
{
    // remove a client
    g_ptr_array_remove(p_client->my_server->clients_list,p_client);

    return TRUE;
}



and the server is astarted only once from the main thread.
regarding GIO, i like to have like control of things so i m just sticking with glib, what i need from glib 
are the special structucures like 
array pointers, sometimes the strings as containers and of course, the mail loop :) .... 

Date: Fri, 22 Oct 2010 10:17:30 +0100
From: chris cvine freeserve co uk
To: jpablolorenzetti hotmail com
CC: maginot junior gmail com; gtk-app-devel-list gnome org
Subject: Re: poll with timeout 0 in main loop

On Fri, 22 Oct 2010 02:57:59 +0000
Juan Pablo L. <jpablolorenzetti hotmail com> wrote:
hi, this is the code that makes the server socket
[snip]

There doesn't seem anything especially wrong with this but you have a
lot of code missing.  In particular, what does your
tcp_server_handle_connection_events() callback do, such as when it
encounters errors (you specify that the callback is to be entered in a
case of G_IO_NVAL and G_IO_ERR), and how do you disconnect sources from
the main loop when they are finished with (I notice also you don't
unref the sources after attaching them to the main loop).  Quite
possibly you are looping in a case of errors or defunct sources.

Probably the best thing you can do is come up with the smallest test
case which demonstrates the error (with say just one socket worker
thread) and post it here.

This is off topic, but glib's gio makes it trivial to construct new
server threads and it does all the hard stuff for you, but you need
glib version 2.22 for gio's socket API.  Glib's gio has no relationship
with GIOChannels, despite the similar names.

Chris
                                          


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]