Re: IO Channel Flush - Assertion Failure



I agree, there seems to be a bug, the question is where the bug lies. 
I think it is legal for write() to return 0  however I have never experienced 
that myself. Also write() does return -1 if EINTR or EAGAIN occurs. I 
have no idea what conditions would cause it to return 0. I would expect
a value between 1 and count inclusive where count is the number of bytes
in the buffer past to write() in the third parameter.

My guess is that the glib code is not where the problem is. Either the OS 
implementation of write() is buggy or there is a subtle bug in your code. 

I cannot imagine how you would fix this problem in either g_io_unix_write() 
or g_io_channel_flush(). If write() return's 0 do you just retry the write(), or 
do you make up an error status? It depends on what it means to get back a
0 from write().

Perhaps someone else knows what would cause write() to return 0. 

BTW: What OS are you using?

Peter Long

----- Original Message ----
From: Christian Bünnig <masala web de>
To: Peter Long <gert2001 yahoo com>
Cc: "gtk-list gnome org" <gtk-list gnome org>
Sent: Tuesday, December 18, 2007 1:38:59 PM
Subject: Re: IO Channel Flush - Assertion Failure


Thanks for hint.

In my case io_write() is the function g_io_unix_write() from giounix.c:

----- snip -----

static GIOStatus
g_io_unix_write (GIOChannel  *channel, 
         const gchar *buf, 
         gsize       count,
         gsize      *bytes_written,
         GError    **err)
{
  GIOUnixChannel *unix_channel = (GIOUnixChannel *)channel;
  gssize result;

 retry:
  result = write (unix_channel->fd, buf, count);

  if (result < 0)
    {
      *bytes_written = 0;

      switch (errno)
        {
#ifdef EINTR
          case EINTR:
            goto retry;
#endif
#ifdef EAGAIN
          case EAGAIN:
            return G_IO_STATUS_AGAIN;
#endif
          default:
            g_set_error (err, G_IO_CHANNEL_ERROR,
                         g_io_channel_error_from_errno (errno),
                         g_strerror (errno));
            return G_IO_STATUS_ERROR;
        }
    }

  *bytes_written = result;

  return G_IO_STATUS_NORMAL;
}

--------- snip ----------
(this code is from svn-trunk)

The function above has no special handling for the case that write()
returns 0. It regards this situation as G_IO_STATUS_NORMAL. However,
g_io_channel_flush() has a different opinion about that - see
g_assert(this_time > 0).
So one of these functions should change its philosophy!

The write()-manpage does not clearly mention what it means if write()
returns 0. In my understanding, if writing data is not possible, it
returns -1 and sets errno to EINTR or EAGAIN .. but maybe this is wrong
and write() returns 0 when there is a EINTR or EAGAIN situation.

I guess this problem should be filed as a bug. Please confirm ..

Christian

On Tue, 2007-12-18 at 09:56 -0800, Peter Long wrote:
> The assert only happens if io_write returns a successful status code
 AND the total bytes_written are less that the bytes in the buffer. So
 io_write() wrote nothing while there was data to write but did not
 report an error. That does sound like a bug to me. I bet the bug is in
 io_write(). It should return an error status if it could not write any more
 data.
> 
> Peter Long
> 
> ----- Original Message ----
> From: Christian Bünnig <masala web de>
> To: "gtk-list gnome org" <gtk-list gnome org>
> Sent: Tuesday, December 18, 2007 11:52:57 AM
> Subject: IO Channel Flush - Assertion Failure
> 
> 
> Hi,
> 
> for data communication between 2 Bluetooth devices I have created IO
> channels on the corresponding sockets. This works well the most time.
> However, sometimes (I could not determine the exact occurrence yet)
> flushing the channel with g_io_channel_flush() fails in that it
 raises
> an assertion error. The failure happens in the line
>   g_assert (this_time > 0);
> in the function below (from giochannel.c)
> 
> ------ snip -------
> 
> GIOStatus
> g_io_channel_flush (GIOChannel *channel, GError **error)
> {
>   GIOStatus status;
>   gsize this_time = 1, bytes_written = 0;
> 
>   g_return_val_if_fail (channel != NULL, G_IO_STATUS_ERROR);
>   g_return_val_if_fail ((error == NULL) || (*error == NULL),  
>                         G_IO_STATUS_ERROR);
> 
>   if (channel->write_buf == NULL || channel->write_buf->len == 0)
>     return G_IO_STATUS_NORMAL;
> 
>   do
>     {
>       g_assert (this_time > 0); /// THIS ASSERTION FAILS ///
> 
>       status = channel->funcs->io_write(channel,
>                                 channel->write_buf->str +
>  bytes_written,
>                                 channel->write_buf->len -
>  bytes_written,
>                                 &this_time, error);
>       bytes_written += this_time;
>     }
>   while ((bytes_written < channel->write_buf->len)
>          && (status == G_IO_STATUS_NORMAL));
> 
>   g_string_erase (channel->write_buf, 0, bytes_written);
> 
>   return status;
> }
> 
> ------- snip --------
> 
> Afaik. assertions are used to detect bugs .. why is it considered as
 a
> bug if channel->funcs->io_write() writes no data (this_time == 0)?
 And
> who is responsible for that assertion failure?
> 
> Thanks for some advice,
> 
> Christian
> 
> _______________________________________________
> gtk-list mailing list
> gtk-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-list
> 
> 
> 






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