How to use GIOChannel to read an Unix socket
Hi, I create a GIOChannel which wraps around a socket on linux: GIOChannel* channel = g_io_channel_unix_new(sock); g_io_add_watch(channel, G_IO_IN, gio_read_socket, NULL)); g_io_add_watch(channel, G_IO_HUP, gio_close_socket, NULL)); And my function gio_read_socket() does get called whenever there is data available on the socket. And I am able to retrieve data using g_io_channel_read_line (). But when the other side of the socket get closed(). My function g_io_channel_read_line() get called infinite number of times with the number of data read = 0. Can you please tell me how can I fix my problem? And my function gio_close_socket() which registered for G_IO_HUP were never get called. static gboolean gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer data) { printf (" gio_read_socket \n"); GIOStatus ret; GError *err = NULL; gchar *msg; gsize len; ret = g_io_channel_read_line (gio, &msg, &len, NULL, &err); if (ret == G_IO_STATUS_ERROR) g_error ("Error reading: %s\n", err->message); printf ("Read %u bytes: %s\n", len, msg); g_free (msg); // Try to close the socket when nothing is there. if (len == 0) { close(g_io_channel_unix_get_fd(gio)); g_io_channel_close(gio); } return TRUE; } Thank you. ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: How to use GIOChannel to read an Unix socket
On Sun, 24 Jan 2010 00:02:49 -0800 silverburgh wrote: > Hi, > > I create a GIOChannel which wraps around a socket on linux: > > GIOChannel* channel = g_io_channel_unix_new(sock); > g_io_add_watch(channel, G_IO_IN, > gio_read_socket, NULL)); > g_io_add_watch(channel, G_IO_HUP, > gio_close_socket, NULL)); > > And my function gio_read_socket() does get called whenever there is > data available on the socket. And I am able to retrieve data using > g_io_channel_read_line (). > But when the other side of the socket get closed(). My function > g_io_channel_read_line() get called infinite number of times with the > number of data read = 0. Can you please tell me how can I fix my > problem? And my function gio_close_socket() which registered for > G_IO_HUP were never get called. > > static gboolean > gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer > data) { >printf (" gio_read_socket \n"); > GIOStatus ret; > GError *err = NULL; > gchar *msg; > gsize len; > > ret = g_io_channel_read_line (gio, &msg, &len, NULL, &err); > if (ret == G_IO_STATUS_ERROR) > g_error ("Error reading: %s\n", err->message); > > printf ("Read %u bytes: %s\n", len, msg); > g_free (msg); > // Try to close the socket when nothing is there. > if (len == 0) { > close(g_io_channel_unix_get_fd(gio)); > g_io_channel_close(gio); > } > > return TRUE; > } You need to check the return value of g_io_channel_read_line() for more than just an error - in particular for G_IO_STATUS_EOF. You also should not normally have a separate callback for a G_IO_HUP condition because POLL_HUP is not of itself a reliable indicator of end of file. (Instead bitwise-or it with G_IO_IN for a single handler.) See this for further details: http://www.greenend.org.uk/rjk/2001/06/poll.html Actually, you have attempted to fix your problem in a different way, by closing the socket when the read data length is 0, assuming that you are doing blocking reads. However, you need to free the GIOChannel object. The easiest way to do that is to call g_io_channel_unref() on the GIOChannel object immediately after you have called g_io_add_watch() on it. g_io_channel_*_new() returns a GIOChannel object with a reference count of one. g_io_add_watch() adds a further reference count - if you decrement it by 1, the callback will be disconnected and the relevant GSource object removed when the callback returns FALSE, which it should do when it detects end-of-file, or if you call g_source_remove() on the return value of g_io_add_watch(). (Incidentally, you are also supposed to use g_io_channel_shutdown() rather than g_io_channel_close(), but that of itself is not sufficient to free the GIOCondition object and it is not necessary anyway in this usage.) I agree that the documentation on this isn't very good. Chris ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: How to use GIOChannel to read an Unix socket
Chris, I have updated my gio_read_socket per your advice. But when the other end closes the socket (the GIOChannel* gio ties to that socket), I get a segmentation fault. I think some how when I call gio_shutdown, it ends up calling gio_read_socket again, and it crashes with a Segmentation fault. My console output: gio shutdown: gio_read_socket (GtkLauncher:5402): GLib-CRITICAL **: g_io_channel_read_line: assertion `channel->is_readable' failed Program received signal SIGSEGV, Segmentation fault. 0x08048aa4 in gio_read_socket (gio=0x8590f50, condition=G_IO_IN, data=0x0) at main.c:230 230 g_error ("Error reading: %s\n", err->message); static gboolean gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer data) { printf (" gio_read_socket \n"); GIOStatus ret; GError *err = NULL; gchar *msg; gsize len; if (condition & G_IO_HUP){ printf ("Read end of pipe died!\n"); return TRUE; } ret = g_io_channel_read_line (gio, &msg, &len, NULL, &err); if (ret == G_IO_STATUS_ERROR) g_error ("Error reading: %s\n", err->message); else if (ret == G_IO_STATUS_EOF) { printf ("gio shutdown: \n"); g_io_channel_shutdown(gio, true, &err); } else { printf ("Read %u bytes: %s\n", len, msg); g_free (msg); } return TRUE; } Thank you for any more help. On Sun, Jan 24, 2010 at 2:47 AM, Chris Vine wrote: > On Sun, 24 Jan 2010 00:02:49 -0800 > silverburgh wrote: >> Hi, >> >> I create a GIOChannel which wraps around a socket on linux: >> >> GIOChannel* channel = g_io_channel_unix_new(sock); >> g_io_add_watch(channel, G_IO_IN, >> gio_read_socket, NULL)); >> g_io_add_watch(channel, G_IO_HUP, >> gio_close_socket, NULL)); >> >> And my function gio_read_socket() does get called whenever there is >> data available on the socket. And I am able to retrieve data using >> g_io_channel_read_line (). >> But when the other side of the socket get closed(). My function >> g_io_channel_read_line() get called infinite number of times with the >> number of data read = 0. Can you please tell me how can I fix my >> problem? And my function gio_close_socket() which registered for >> G_IO_HUP were never get called. >> >> static gboolean >> gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer >> data) { >> printf (" gio_read_socket \n"); >> GIOStatus ret; >> GError *err = NULL; >> gchar *msg; >> gsize len; >> >> ret = g_io_channel_read_line (gio, &msg, &len, NULL, &err); >> if (ret == G_IO_STATUS_ERROR) >> g_error ("Error reading: %s\n", err->message); >> >> printf ("Read %u bytes: %s\n", len, msg); >> g_free (msg); >> // Try to close the socket when nothing is there. >> if (len == 0) { >> close(g_io_channel_unix_get_fd(gio)); >> g_io_channel_close(gio); >> } >> >> return TRUE; >> } > > You need to check the return value of g_io_channel_read_line() for more > than just an error - in particular for G_IO_STATUS_EOF. You also should > not normally have a separate callback for a G_IO_HUP condition because > POLL_HUP is not of itself a reliable indicator of end of file. > (Instead bitwise-or it with G_IO_IN for a single handler.) > > See this for further details: > http://www.greenend.org.uk/rjk/2001/06/poll.html > > Actually, you have attempted to fix your problem in a different way, > by closing the socket when the read data length is 0, assuming that you > are doing blocking reads. However, you need to free the GIOChannel > object. The easiest way to do that is to call g_io_channel_unref() on > the GIOChannel object immediately after you have called > g_io_add_watch() on it. g_io_channel_*_new() returns a GIOChannel > object with a reference count of one. g_io_add_watch() adds a further > reference count - if you decrement it by 1, the callback will be > disconnected and the relevant GSource object removed when the callback > returns FALSE, which it should do when it detects end-of-file, or if > you call g_source_remove() on the return value of g_io_add_watch(). > (Incidentally, you are also supposed to use g_io_channel_shutdown() > rather than g_io_channel_close(), but that of itself is not sufficient > to free the GIOCondition object and it is not necessary anyway in this > usage.) I agree that the documentation on this isn't very good. > > Chris > > > ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: How to use GIOChannel to read an Unix socket
Hi silverburgh, On Tue, 26 Jan 2010 23:59:11 -0800 you wrote: > > I have updated my gio_read_socket per your advice. No you haven't. Chris explicitly said you need to "free the GIOChannel object"and that using g_io_channel_shutdown "of itself is not sufficient". I quote: > Actually, you have attempted to fix your problem in a different way, > by closing the socket when the read data length is 0, assuming that you > are doing blocking reads. However, you need to free the GIOChannel > object. The easiest way to do that is to call g_io_channel_unref() on > the GIOChannel object immediately after you have called > g_io_add_watch() on it. g_io_channel_*_new() returns a GIOChannel > object with a reference count of one. g_io_add_watch() adds a further > reference count - if you decrement it by 1, the callback will be > disconnected and the relevant GSource object removed when the callback > returns FALSE, which it should do when it detects end-of-file, or if > you call g_source_remove() on the return value of g_io_add_watch(). > (Incidentally, you are also supposed to use g_io_channel_shutdown() > rather than g_io_channel_close(), but that of itself is not sufficient > to free the GIOCondition object and it is not necessary anyway in this > usage.) I agree that the documentation on this isn't very good. So you need to change how you create the channel object (which you haven't posted so I have to assume you didn't change it) _AND_ you need to ensure that the callback returns FALSE when it detects end of file. Try doing what Chris said and see if that helps. Rob ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list
Re: How to use GIOChannel to read an Unix socket
On Tue, 26 Jan 2010 23:59:11 -0800 silverburgh wrote: > I have updated my gio_read_socket per your advice. > But when the other end closes the socket (the GIOChannel* gio ties to > that socket), > I get a segmentation fault. I think some how when I call > gio_shutdown, it ends up calling gio_read_socket again, and it crashes > with a Segmentation fault. > > My console output: > gio shutdown: > gio_read_socket > > (GtkLauncher:5402): GLib-CRITICAL **: g_io_channel_read_line: > assertion `channel->is_readable' failed > > Program received signal SIGSEGV, Segmentation fault. > 0x08048aa4 in gio_read_socket (gio=0x8590f50, condition=G_IO_IN, > data=0x0) at main.c:230 > 230 g_error ("Error reading: %s\n", > err->message); > > > static gboolean > gio_read_socket (GIOChannel *gio, GIOCondition condition, gpointer > data) { > printf (" gio_read_socket \n"); > GIOStatus ret; > GError *err = NULL; > gchar *msg; > gsize len; > > if (condition & G_IO_HUP){ > printf ("Read end of pipe died!\n"); > return TRUE; > } > > ret = g_io_channel_read_line (gio, &msg, &len, NULL, &err); > if (ret == G_IO_STATUS_ERROR) > g_error ("Error reading: %s\n", err->message); > else if (ret == G_IO_STATUS_EOF) { > printf ("gio shutdown: \n"); > g_io_channel_shutdown(gio, true, &err); > } else { > printf ("Read %u bytes: %s\n", len, msg); > g_free (msg); > } > > return TRUE; > } > > Thank you for any more help. You need to return FALSE in the callback if G_IO_HUP or G_IO_STATUS_EOF is detected, since that will cause disconnection of the callback from the glib main loop. If you have previously called g_io_channel_unref() after the call to g_io_add_watch(), then this will also dispose of the GIOChannel object, so don't try to access it again. Chris ___ gtk-list mailing list gtk-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-list