Thread: Exiting GTK+, allowing CLI to continue

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    129

    Exiting GTK+, allowing CLI to continue

    My GUI currently never programmatically exits even though I push the X and the window disappears, so I have to exit the terminal thereby losing Valgrind's help (unless the program crashes). In the following code fragment which I thought would do this, w is the window.
    Code:
        g_signal_connect(G_OBJECT(w), "delete_event", G_CALLBACK(delete_event), NULL);
        
        g_signal_connect(G_OBJECT(w), "destroy", G_CALLBACK(destroy), NULL);
    And I define those callbacks thusly:
    Code:
    void destroy(GtkWidget *widget, gpointer data){
        gtk_main_quit();
    }
    
    gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data){
        return FALSE;
    }
    I thought that should work?

    Thanks!

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Using valgrind to do "memory profiling" on a gtk executable is a waste of time anyway. If you want a more detailed explanation from the professionals, just google "valgrind gtk+".

    ps. your callbacks are fine, the problem is what I just referred to. You can do this, b.t.w:
    Code:
    g_signal_connect(G_OBJECT(w), "delete_event", G_CALLBACK(gtk_main_quit), NULL);
        
        g_signal_connect(G_OBJECT(w), "destroy", G_CALLBACK(gtk_main_quit), NULL);
    You only need a fullblown callback if there is more complicated clean up to be done.
    Last edited by MK27; 04-10-2009 at 08:30 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  3. #3
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    I looked thru a couple threads returned by Google; while you're right about Valgrind, they don't seem to have the issue of the hanging terminal (because they can actually see Valgind's report). I'd like to get around it whether Valgrind will still be useful or not; currently I must Ctrl+Shift+T, close the old gnome-terminal tab, then resume my debugging. I'd like it to be a seamless transition from one GTK+ session to the next, like a CLI program allows.

    Or has the GTK+ development team purposely blocked Valgrind's output to avoid any more such bug reports?

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Jesdisciple View Post
    Or has the GTK+ development team purposely blocked Valgrind's output to avoid any more such bug reports?
    No, for sure not. But it could be a related issue, in that gtk's "cleanup" appears so unreal that valgrind does not consider the process closed. If that makes sense.

    I almost never use valrind anyway (shame on me) but I just ran "valgrind mygtkapp", then closed the GUI window, and valgrind appears to exit cleanly to me (that is, it prints a summary and then you return to the command line).
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    Would it be unwise to call gtk_main_quit() and then exit(EXIT_SUCCESS) from the callback?

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Jesdisciple View Post
    Would it be unwise to call gtk_main_quit() and then exit(EXIT_SUCCESS) from the callback?
    No. But as long as you have a "return" statement at the end of main (after "gtk_main();") that will happen anyway after gtk_main_quit()
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    It actually worked. So apparently some function within gtk_main is never returning, surely because I did something wrong. This is my first GTK project, as you probably guessed, and I don't have a clue where to look for the bug. So if you or anyone else could give a hint, that would be fantastic. Here's my prime suspect - the source with all the GTK logic, which also happens to be the least stable. (I've cut out the irrelevant CLI logic, along with all the other functions the GUI code doesn't yet call.) Note that much of the start code is from the tutorial I used; I left it there because, for all I know, it may contain the problem.
    Code:
    #ifdef	__cplusplus
    extern "C" {
    #endif
    
    #include "../Jesdisciple/toolkit.h"
    #include "interface.h"
    #include "outline.h"
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    
    #ifndef INTERFACE
    	#define INTERFACE TEXTUAL
    #endif
    
    static struct outline *o = (struct outline *)NULL;
    
    #if INTERFACE == GRAPHICAL
    
    #include <gtk/gtk.h>
    
    static GtkWidget *w = (GtkWidget *)NULL;
    
    enum{
       TITLE_COLUMN,
       AUTHOR_COLUMN,
       CHECKED_COLUMN,
       N_COLUMNS
    };
    void prompt(struct outline_interface *this, char *message, size_t length, void (*receive)(char *, void **), void **args){
    	GtkWidget *dialog = gtk_dialog_new_with_buttons("Outliner", (GtkWindow *)w, GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_CANCEL, GTK_STOCK_OK, NULL);
    	GtkVBox *content = (GtkVBox *)gtk_dialog_get_content_area((GtkDialog *)dialog);
    	GtkEntry *entry = (GtkEntry *)gtk_entry_new_with_max_length((gint)length);
    	gtk_container_add((GtkContainer *)content, (GtkWidget *)entry);
    	gtk_widget_show_all(dialog);
    	g_signal_connect(G_OBJECT(dialog), "response", G_CALLBACK(receive), NULL);
    	gtk_dialog_run((GtkDialog *)dialog);
    }
    
    void set_title(char *title, void **args){
    	gtk_window_set_title((GtkWindow *)w, title);
    }
    
    void destroy(GtkWidget *widget, gpointer data){
    	gtk_main_quit();
    	exit(EXIT_SUCCESS);
    }
    
    gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data){
    	return FALSE;
    }
    
    void start(struct outline_interface *this){
    	GtkTreeStore *store;
    	GtkWidget *tree;
    	GtkTreeViewColumn *column;
    	GtkCellRenderer *renderer;
    	
    	w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    	
    	g_signal_connect(G_OBJECT(w), "delete_event", G_CALLBACK(delete_event), NULL);
    	
    	g_signal_connect(G_OBJECT(w), "destroy", G_CALLBACK(destroy), NULL);
    	
    	gtk_container_set_border_width(GTK_CONTAINER(w), 10);
    
    	/* Create a model.  We are using the store model for now, though we
    	* could use any other GtkTreeModel */
    	store = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
    
    	void *args[1] = {NULL};
    	this->prompt(this, "Enter a title for this outline.", 26, set_title, args);
    	
    	/* Create a view */
    	tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL (store));
    
    	/* The view now holds a reference.  We can get rid of our own
    	* reference */
    	g_object_unref(G_OBJECT(store));
    
    	/* Create a cell render and arbitrarily make it red for demonstration
    	* purposes */
    	renderer = gtk_cell_renderer_text_new();
    	g_object_set(G_OBJECT(renderer), "foreground", "red", NULL);
    
    	/* Create a column, associating the "text" attribute of the
    	* cell_renderer to the first column of the model */
    	column = gtk_tree_view_column_new_with_attributes ("Author", renderer, "text", AUTHOR_COLUMN, NULL);
    
    	/* Add the column to the view. */
    	gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
    
    	/* Second column.. title of the book. */
    	renderer = gtk_cell_renderer_text_new();
    	column = gtk_tree_view_column_new_with_attributes("Title", renderer, "text", TITLE_COLUMN, NULL);
    	gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
    
    	/* Last column.. whether a book is checked out. */
    	renderer = gtk_cell_renderer_toggle_new();
    	column = gtk_tree_view_column_new_with_attributes("Checked out", renderer, "active", CHECKED_COLUMN, NULL);
    	gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
    	
    	/* This packs the tree into the window (a gtk container). */
    	gtk_container_add(GTK_CONTAINER(w), tree);
    	
    	gtk_widget_show_all(w);
    	
    	gtk_main();
    	
    	if(o != (struct outline *)NULL)
    		o->free(o);
    }
    #endif
    
    #ifdef __cplusplus
    }
    #endif

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Treeview always gives me a headache

    You might want to ask your original question (or your current version thereof) at gtkforums; you might have to wait a while for an answer but there are a few gtk+ wizards in regular attendance there.

    I do not know of any debuggers or tools that can be used effectively with gtk because of the threading; when you have a problem you are pretty much left with a stick in your hand, which means breaking stuff down, tracing things manually, and grinding much tooth.
    Last edited by MK27; 04-10-2009 at 01:06 PM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    Okay, thanks for the referral! I managed to eliminate almost all of start (including all tree logic), so now I'm even more perplexed than before...
    Last edited by Jesdisciple; 04-10-2009 at 01:46 PM.

  10. #10
    Registered User
    Join Date
    Aug 2008
    Posts
    129
    *backs up* Wait a sec... I just tried it with GDB and it has problems after gtk_main, on the line just before return 0; - then it hung just like Valgrind. On that line, I free a global but GDB complained that it couldn't access 0x33. I tried printing the address of the variable and it just gives the same complaint for the printf call. Then I tried simply running the program without a debugger and didn't have any problems.

    I ran it through GDB again and the only strange thing was this:
    Code:
    0xb77a6685 in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
    (gdb) 
    Single stepping until exit from function __libc_start_main, 
    which has no line number information.
    
    Program exited normally.
    Then I tried Valgrind again; no problems. And the original strange behavior of GDB only happens when I set a breakpoint on a function other than main, but it still exits normally. Should I submit a bug report for GCC...?

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 11-03-2008, 09:48 PM
  2. Gnome GTK / Spawn CLI app - read output
    By MtOzOr in forum Linux Programming
    Replies: 7
    Last Post: 09-08-2008, 06:41 AM