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 <chris cvine freeserve co uk> wrote:
> On Sun, 24 Jan 2010 00:02:49 -0800
> silverburgh <silverburgh meryl gmail com> 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
>
>
>


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