RE: poll with timeout 0 in main loop
this is almost the complete code. you can see all the flow here. basically, the main.c starts the server thread (gm_tcp_server), inside the server thread the application sits waiting for new connection, just sitting waiting consumes 100% of the CPU (without accepting any connection yet), the code of the server is in file gm_tcp_server.c. the rest of the code is just in case you need it for reference. thanks! Date: Fri, 22 Oct 2010 10:17:30 +0100 From: ch...@cvine.freeserve.co.uk To: jpablolorenze...@hotmail.com CC: maginot.jun...@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 + Juan Pablo L. jpablolorenze...@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 ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
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; }
Re: poll with timeout 0 in main loop
On Fri, 22 Oct 2010 10:37:01 + Juan Pablo L. jpablolorenze...@hotmail.com wrote: i attached the code but did not make thru, here is the server code: Something odd is going on. I see you are using GIOChannel not to do any reading, but in order to notify you that a connection is available. poll()/select() of course support this in unix-like systems, but I don't know if GIOChannel does (I have never tried). Possibly it only works if you set the channel as non-blocking with g_io_channel_set_flags() rather than by manipulating the file descriptor directly, which you have done. Again, I don't know. Sending snippets of code really isn't going to help. It could of course be other things, such as you not having initialized glib for threads correctly. You need to send the simplest test case which demonstrates the problem, in compilable form: given the nature of the problem you should be able to reproduce it with very simple code. Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
Re: poll with timeout 0 in main loop
On Fri, 22 Oct 2010 13:53:55 +0100 Chris Vine ch...@cvine.freeserve.co.uk wrote: On Fri, 22 Oct 2010 10:37:01 + Juan Pablo L. jpablolorenze...@hotmail.com wrote: i attached the code but did not make thru, here is the server code: Something odd is going on. I see you are using GIOChannel not to do any reading, but in order to notify you that a connection is available. poll()/select() of course support this in unix-like systems, but I don't know if GIOChannel does (I have never tried). Possibly it only works if you set the channel as non-blocking with g_io_channel_set_flags() rather than by manipulating the file descriptor directly, which you have done. Again, I don't know. Actually, in this usage (attaching the file descriptor of a listening socket to a main loop) there is no need to make the file descriptor non-blocking since you will not make any blocking calls on it until you actually get to call accept() to establish the connection, and you may get undefined behaviour if you do - I don't know what POSIX says about that when you attempt to use poll() with it. Once poll() indicates that a connection is available, accept() can't block anyway. Does it work if you omit your call to fctl()? Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list
RE: poll with timeout 0 in main loop
Hi Chris, yes it works without setting it as non-blocking so i decided to leave none blocking just in case .. :) anyways i was preparing the test code to send to you guys but i discovered that in the test code the cpu usage is 0% (as i would expect in the real application) ... the code i was going to send was a stripped version of the original code so that ... but there is something that might be very important but have not mention yet . i also created a GSource to run functions in other main loops (for example i use this to fire the connection cleaning code in the server when a connection dies) asynchronously, anyways, this is makes me very suspicious now: static gboolean async_callback_prepare(GSource *p_source,int *p_timeout) { AsyncCallbackSource *async_source = (AsyncCallbackSource *)p_source; gboolean ret; *p_timeout = 0; g_mutex_lock(async_source-mutex1); ret = g_queue_is_empty(async_source-callback_list); g_mutex_unlock(async_source-mutex1); return !ret; } i think i misunderstood the documentation here and maybe this is the 0 being passed to poll ??? i think i will test this in the real code and let you know asap Date: Fri, 22 Oct 2010 14:27:54 +0100 From: ch...@cvine.freeserve.co.uk To: ch...@cvine.freeserve.co.uk CC: jpablolorenze...@hotmail.com; gtk-app-devel-list@gnome.org Subject: Re: poll with timeout 0 in main loop On Fri, 22 Oct 2010 13:53:55 +0100 Chris Vine ch...@cvine.freeserve.co.uk wrote: On Fri, 22 Oct 2010 10:37:01 + Juan Pablo L. jpablolorenze...@hotmail.com wrote: i attached the code but did not make thru, here is the server code: Something odd is going on. I see you are using GIOChannel not to do any reading, but in order to notify you that a connection is available. poll()/select() of course support this in unix-like systems, but I don't know if GIOChannel does (I have never tried). Possibly it only works if you set the channel as non-blocking with g_io_channel_set_flags() rather than by manipulating the file descriptor directly, which you have done. Again, I don't know. Actually, in this usage (attaching the file descriptor of a listening socket to a main loop) there is no need to make the file descriptor non-blocking since you will not make any blocking calls on it until you actually get to call accept() to establish the connection, and you may get undefined behaviour if you do - I don't know what POSIX says about that when you attempt to use poll() with it. Once poll() indicates that a connection is available, accept() can't block anyway. Does it work if you omit your call to fctl()? Chris ___ gtk-app-devel-list mailing list gtk-app-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-app-devel-list