How to use GIOChannel to read an Unix socket

2010-01-24 Thread silverburgh
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

2010-01-24 Thread Chris Vine
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

2010-01-26 Thread silverburgh
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

2010-01-27 Thread Robert Pearce
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

2010-01-27 Thread Chris Vine
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