Search code examples
cgtk3glib

GTK IOChannel - How to deal with G_IO_IN event


thanks for the time you spend with my question !

My goal : read a logfile, display it into a TextView widget then update it each time a new line is added to the file (quite simple, it seems)

Problem : It seems that the G_IO_IN condition is always met, even for G_STATUS_EOF. So, the program hangs and doesn't display anything.

Here are some code extracts :

1st, open the file, read it and display it into the TextView (it works perfectly) :

// Get the TextBuffer then go to the latest position (not sure it is useful)
txtBuf=gtk_text_view_get_buffer((GtkTextView *)tvLogs);
gtk_text_buffer_get_end_iter(txtBuf, &txtIter);

// Connect logfile to new IOChannel and add_watch to G_IO_IN condition
chanErr=g_io_channel_new_file("./errorlog.log","r", &error);
g_io_add_watch(chanErr, G_IO_IN, (GIOFunc)DisplayLogs, NULL);

// Read the whole file and display it into the TextView

ret=g_io_channel_read_to_end(chanErr,&file, &fileLen, &err) 
g_assert(ret == G_IO_STATUS_NORMAL);

// Insert file read into the TextView 
gtk_text_buffer_insert(txtBuf, &txtIter, file, fileLen);

At this point, everything is running well... Here is the callback connected to G_IO_IN condition :

gboolean DisplayLogs(GIOChannel *chanErr, GIOCondition cond, gpointer data) 
{
GtkWidget *tvLogs;
gchar *buf;
gsize bufLen;
GError *err=NULL;
GtkTextBuffer *txtBuf;
GtkTextIter txtIter;
GIOStatus ret;

// Retrieve the TextView
tvLogs=GTK_WIDGET(gtk_builder_get_object(builder,(gchar*)"tvLogs"));
g_assert(tvLogs);

// Try to read 1 line
ret=g_io_channel_read_line(chanErr, &buf, &bufLen, NULL, &err);
if (ret!=G_STATUS_NORMAL) {
  switch (ret) {
        case G_IO_STATUS_ERROR : g_warning("G_IO_STATUS_ERROR"); break;
        case G_IO_STATUS_EOF : g_warning("G_IO_STATUS_EOF"); break;
        case G_IO_STATUS_AGAIN : g_warning("G_IO_STATUS_AGAIN"); break;
    }
    if (err)
        g_warning(err->message);
}

//
     ....
     other stuff to update info displayed but never reached
//

return TRUE;
}

When application starts : it loops infinitively on "G_STATUS_EOF". It seems that this event triggers G_IO_IN condition and fire the callback.

Any idea ?

Many thanks in advance.

Regards.

-- Vincent


Solution

  • Well, since nobody answered, I have to find a solution by myself (which is quite a good thing indeed).

    Problem was : how to display in a TextView the log entries coming from a file.

    Solution found :

    1. To produce the log, the application uses zlog API so, instead of watching for the logfile, reading new entries and displaying them in the textview, I've done the following :
    2. Add a custom output callback in the zlog API (very nice functionality of the API)
    3. The callback simply "print" the zlog formated message (date - time - function - severtity - message) into at the end of the TextView widget.
    4. Simultaneously, ZLog writes the message into the logfile (due to the zlog.conf file).

    Result is nice. I have the log file AND the windowed log.

    Problem solved (or workarounded it depends :-) )

    Regards.