Re: What causes GLib I/O Channels operations to use up 100% CPU in GTK+ app.?



Attaching file in email body...

At 02:36 AM 10/12/2006, Daniel Yek wrote:
Hi,

I am attaching the source code of a small test program here.

Could somebody enlighten me why after an I/O Channel operation (g_io_channel_shutdown() here), the GTK+ program started to use up 100% CPU?

Is it monitoring something? Do I need to undo g_io_add_watch() somehow? What operation is needed to not get into such situation?

Thanks.


#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>

char buf[] = "Line 1\nLine 2\nLine 3\nLine 4\n";
int mypipe[2];
GIOChannel *giochannel;

void
gio_shutdown(GIOChannel *giochannel)
{
    GError *gerror = NULL;
    GIOStatus status;

    printf("Entering gio_shutdown\n");
    // Shutdown I/O Channel would close the file descriptor, mypipe[0]!
    status = g_io_channel_shutdown(giochannel,
                                   FALSE,       // Flush?
                                   &gerror);
    if (status != G_IO_STATUS_NORMAL)
    {
        fprintf(stderr, "ERROR shutting down I/O Channel\n");
    }
    if (gerror) g_error_free(gerror);
}

static gboolean
gio_channel_hup(GIOChannel *giochannel, GIOCondition giocondition, gpointer data)
{
    printf("Received HUP. Shutting down I/O Channel.\n");
    gio_shutdown(giochannel);
    return FALSE;
}

void read_io_channel(GIOChannel *giochannel)
{
    gchar *str = NULL;
    gsize length = 0;
    GError *gerror = NULL;
    GIOStatus status;
    printf("Entering read_io_channel\n");

    status = g_io_channel_read_line(giochannel, &str, &length,
                                    NULL,      // terminator_pos
                                    &gerror);
    if (status != G_IO_STATUS_NORMAL)
    {
        fprintf(stderr, "ERROR reading I/O Channel\n");
    }
    printf("str = %s\n", str);
    if (gerror) g_error_free(gerror);
}

// Type: GIOFunc
// The function should return FALSE if the event source should be removed.
static gboolean
gio_channel_handler(GIOChannel *giochannel, GIOCondition giocondition, gpointer data)
{
    fprintf(stderr, "gio_channel_handler().\n");
    if (giocondition == G_IO_IN)
    {
      read_io_channel(giochannel);
      return TRUE;
    }
    else if (giocondition == G_IO_HUP)
    {
      gio_shutdown(giochannel);
    }
    return FALSE;
}

void
dialog_handler(GtkDialog *dialog, gint response, gpointer data)
{
    printf("Entering dialog_handler\n");
    switch(response)
    {
    case GTK_RESPONSE_DELETE_EVENT:
        gtk_main_quit();
        break;

    // Close write-end of the pipe and then write to it causes CPU to max-up.
    case GTK_RESPONSE_APPLY: // write
        fprintf(stderr, "Writing!\n");
        if (-1 == write(mypipe[1], buf, sizeof(buf)))
        {
            fprintf(stderr, "ERROR writing to pipe.\n");
        }
        printf("Succeeded writing to pipe!\n");
        break;
    case GTK_RESPONSE_YES:   // read
        fprintf(stderr, "Reading...\n");
        read_io_channel(giochannel);
        break;
    case GTK_RESPONSE_CANCEL:  // Close write-end
        fprintf(stderr, "Closing the write-end...\n");
        close(mypipe[1]);
        break;
    case GTK_RESPONSE_NO:  // Close read-end of the pipe
        fprintf(stderr, "Closing the read-end...\n");
        close(mypipe[0]);
        break;
    case GTK_RESPONSE_HELP: // Shutdown I/O channels
        fprintf(stderr, "Shutting down I/O channels...\n");
        gio_shutdown(giochannel);
        break;
    default:
        printf("ERROR: Unknown response: %x\n", response);
        break;
    }
    return;
}

GtkDialog *
create_user_interface()
{
    GtkDialog *dialog;

    dialog = GTK_DIALOG(
      gtk_dialog_new_with_buttons("iochannel Test!", // Title
                                  NULL,              // Parent
                                  0,                 // GtkDialogFlags
                                  // It is OK to have only GTK_RESPONSE_*,
                                  // without the label below!
                                  "_write", GTK_RESPONSE_APPLY,
                                  "_read",  GTK_RESPONSE_YES,
                                  "_closeWrite", GTK_RESPONSE_CANCEL,
                                  "c_loseRead", GTK_RESPONSE_NO,
                                  "_shutdownIOChannel", GTK_RESPONSE_HELP,
NULL)); // Must be NULL-terminated!
    gtk_dialog_set_default_response(dialog, GTK_RESPONSE_CLOSE);
    g_signal_connect(dialog, "response", G_CALLBACK(dialog_handler),
      /*userdata*/ NULL);
    gtk_widget_show_all(GTK_WIDGET(dialog));

    return dialog;
}

int main(int argc, char **argv)
{
    GtkDialog *dialog;
    gtk_init(&argc, &argv);
    if (-1 == pipe(mypipe))
    {
        fprintf(stderr, "ERROR creating pipe\n");
        exit(1);
    }

    giochannel = g_io_channel_unix_new(mypipe[0]);
g_io_add_watch(giochannel, G_IO_IN|G_IO_HUP, gio_channel_handler, /*userdata*/ NULL); //g_io_add_watch(giochannel, G_IO_HUP, gio_channel_hup, /*userdata*/ NULL);

    dialog = create_user_interface();

    // gtk_dialog_run() will dismiss after get one result.
    // printf("Running dialog box\n");
    // gtk_dialog_run(dialog);

    printf("Entering gtk_main\n");
    gtk_main();
    g_free(dialog);

    return 0;
}




--
Daniel Yek




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