From 82fe0199e309a36aa36121157e070977f3eb2d9a Mon Sep 17 00:00:00 2001 From: Bill Adams Date: Mon, 15 Jan 2001 06:17:50 +0000 Subject: [PATCH] Core Dump Fix, So Help Me God. git-svn-id: http://svn.code.sf.net/p/xqf/code/trunk@40 d2ac09be-c843-0410-8b1f-f8a84130e0ec --- xqf/ChangeLog | 10 ++++++++++ xqf/src/server.c | 19 +++++++++++++++++-- xqf/src/server.h | 2 ++ xqf/src/source.c | 15 +++++++++++++-- xqf/src/srv-list.c | 44 ++++++++++++++++++++++++++++++++------------ xqf/src/stat.c | 2 +- xqf/src/statistics.c | 2 +- xqf/src/xqf.c | 25 ++++++++++++++++++++++--- 8 files changed, 98 insertions(+), 21 deletions(-) diff --git a/xqf/ChangeLog b/xqf/ChangeLog index 1dd40e2..31ab23e 100644 --- a/xqf/ChangeLog +++ b/xqf/ChangeLog @@ -1,3 +1,13 @@ +Feb 14, 2001: Bill Adams +-Oh dear god, I think I fixed the core dumps related + to the reference counting on the server structures. + At least to the best of my ability, I cannot make + the server references increase or decrease + over time: i.e. the program always exits with + a reference count of one on all server structures. + I could not figure out why it was 1 and not zero + but I will deal with that later. + Feb 13, 2001: Bill Adams -Changed version to 0.9.6f, added announcement dir and announcement. diff --git a/xqf/src/server.c b/xqf/src/server.c index a55aafe..b572132 100644 --- a/xqf/src/server.c +++ b/xqf/src/server.c @@ -81,7 +81,8 @@ static struct server *server_new (struct host *h, unsigned short port, server = g_malloc0 (sizeof (struct server)); debug (6, "server_new() -- Server %lx", server); - server_ref (server); + + server_ref (server); server->host = h; host_ref (h); /* Increse the refernece count on the host struct */ @@ -258,9 +259,12 @@ void userver_unref (struct userver *s) { if (!s) return; - + s->ref_count--; + debug (6, "userver_unref() -- UServer %lx ref now at %d", + s, s->ref_count); + if (s->ref_count <= 0) { node = userver_hash_func (s->hostname, s->port); uservers.nodes[node] = g_slist_remove (uservers.nodes[node], s); @@ -444,9 +448,12 @@ void uservers_to_servers (GSList **uservers, GSList **servers) { struct userver *us; GSList *tmp = *uservers; + debug (6, "uservers_to_servers() -- uservers %lx tmp %lx", uservers, tmp); while (tmp) { us = (struct userver *) tmp->data; + debug (7, "uservers_to_servers() -- Check userver %lx", us); if (us->s) { + debug (7, "uservers_to_servers() -- server %lx userver %lx", us->s, us); *servers = server_list_append (*servers, us->s); *uservers = g_slist_remove (*uservers, us); @@ -457,9 +464,17 @@ void uservers_to_servers (GSList **uservers, GSList **servers) { } tmp = tmp->next; } + debug (6, "uservers_to_servers() -- Done."); } +/* + server_lists_intersect() -- Find servers that are + in two lists (by reference). The first arg gets a list + of servers not in both lists. The second list gets servers + removed that are in both lists. +*/ + void server_lists_intersect (GSList **list1, GSList **list2) { GSList *list3 = NULL; GSList *tmp; diff --git a/xqf/src/server.h b/xqf/src/server.h index effeab7..cd74db7 100644 --- a/xqf/src/server.h +++ b/xqf/src/server.h @@ -45,6 +45,7 @@ extern int servers_total (void); extern int uservers_total (void); extern GSList *all_servers (void); + extern int parse_address (char *str, char **addr, unsigned short *port); extern struct server *userver_set_host (struct userver *s, struct host *h); @@ -86,6 +87,7 @@ static inline GSList *server_list_append (GSList *list, struct server *server) { } static inline GSList *server_list_remove (GSList *list, struct server *s) { + debug (6, "server_list_remove() -- remove server %lx from list %lx", s, list); if (g_slist_find (list, s)) { list = g_slist_remove (list, s); server_unref (s); diff --git a/xqf/src/source.c b/xqf/src/source.c index 987c748..8d9fd5e 100644 --- a/xqf/src/source.c +++ b/xqf/src/source.c @@ -58,6 +58,7 @@ static void save_list (FILE *f, struct master *m) { if (!m->servers) return; + debug (6, "save_list() -- Saving Server List \"%s\"", m->name ); #ifdef DEBUG fprintf (stderr, "Saving server list \"%s\"...\n", m->name); @@ -97,6 +98,7 @@ void save_favorites (void) { FILE *f; char *realname; + debug (6, "save_favorites() --"); realname = file_in_dir (user_rcdir, FILENAME_FAVORITES); while (1) { @@ -125,6 +127,7 @@ static void save_lists (GSList *list, const char *filename) { char *realname; struct zstream z; + debug (6, "save_lists() -- %s", filename); realname = file_in_dir (user_rcdir, filename); if (!list) { @@ -363,6 +366,12 @@ static void master_add_server (struct master *m, char *str, host_ref (h); if ((s = server_add (h, port, type)) != NULL) { m->servers = server_list_prepend (m->servers, s); + /* Since the server_add increments the ref count, and + server_list_prepend ups the ref_count, we should + unref it once because we are only keeping it in + one list after this function. + */ + server_unref (s); } host_unref (h); } @@ -1014,6 +1023,7 @@ void init_masters (int update) { void free_masters (void) { GSList *tmp; + debug (6, "free_masters() --"); save_favorites (); if (default_save_lists) { @@ -1023,7 +1033,7 @@ void free_masters (void) { g_slist_free (tmp); if (default_save_srvinfo) { - tmp = all_servers (); + tmp = all_servers (); /* free done in two lines */ save_server_info (FILENAME_SRVINFO, tmp); server_list_free (tmp); } @@ -1057,6 +1067,7 @@ static void master_list_add (GSList **masters, GSList **servers, GSList **uservers, struct master *m) { GSList *tmp; + debug (6, "master_list_add() -- master '%s'", m->name); if (m->isgroup || m == favorites) { if (servers) { *servers = server_list_append_list (*servers, favorites->servers, @@ -1105,7 +1116,7 @@ void master_selection_to_lists (GSList *list, GSList **masters, GSList **servers, GSList **uservers) { struct master *m; GSList *tmp; - + debug (6, "master_selection_to_lists() --"); for (tmp = list; tmp; tmp = tmp->next) { m = (struct master *) tmp->data; uservers_to_servers (&m->uservers, &m->servers); diff --git a/xqf/src/srv-list.c b/xqf/src/srv-list.c index 714472a..47629e8 100644 --- a/xqf/src/srv-list.c +++ b/xqf/src/srv-list.c @@ -101,6 +101,8 @@ static int server_clist_refresh_row (struct server *s, int row) { assemble_server_address (buf1, 256, s); text[1] = buf1; + debug (7, "server_clist_refresh_row() -- Row %d", row); + if (s->ping >= 0) { g_snprintf (buf2, 32, "%d", (s->ping > MAX_PING)? MAX_PING : s->ping); text[2] = buf2; @@ -326,10 +328,12 @@ void player_clist_redraw (void) { void server_clist_sync_selection (void) { GList *selection; + debug (7, "server_clist_sync_selection() --"); if (!sync_selection_blocked) { selection = server_clist->selection; if (cur_server) { + debug (7, "server_clist_sync_selection() -- unref server %lx", cur_server); server_unref (cur_server); cur_server = NULL; } @@ -372,9 +376,10 @@ int server_clist_refresh_server (struct server *s) { } else { if ((s->filters & cur_filter) == cur_filter) { + debug (6, "server_clist_refresh_server() -- Server %lx needs to be added."); row = server_clist_refresh_row (s, -1); gtk_clist_set_row_data_full (server_clist, row, s, - (GtkDestroyNotify) server_unref); + (GtkDestroyNotify) server_unref); server_ref (s); return TRUE; } @@ -385,6 +390,9 @@ int server_clist_refresh_server (struct server *s) { void server_clist_select_one (int row) { + + debug (7, "server_clist_select_one() -- Row %d", row); + sync_selection_blocked = TRUE; gtk_clist_unselect_all (server_clist); sync_selection_blocked = FALSE; @@ -435,6 +443,8 @@ void server_clist_selection_visible (void) { GtkVisibility vis; int min; + debug (7, "server_clist_selection_visible() -- "); + if (!rows) return; @@ -482,6 +492,7 @@ void server_clist_redraw (void) { char buf[256]; int row; + debug (7, "server_clist_redraw() --"); gtk_clist_freeze (server_clist); for (row = 0; row < server_clist->rows; row++) { @@ -503,6 +514,8 @@ void server_clist_set_list (GSList *servers) { int row; GSList *filtered; + debug (7, "server_clist_set_list() -- list %lx", servers); + filtered = build_filtered_list (cur_filter, servers); gtk_clist_freeze (server_clist); @@ -516,12 +529,13 @@ void server_clist_set_list (GSList *servers) { gtk_clist_set_row_data_full (server_clist, row, server, (GtkDestroyNotify) server_unref); /* - Because the build_filtered_list add a reference count - to the server structure and because we are going - to free that list, we DO NOT need to add a reference - count to the server structure. + Because the a destroy event on the server_clist will + call server_unref, we want to add a reference to + count to the server. Note if we comment out both + the ref line and the list_free line we have a net sum + of zero. But just for clarity... */ - /* server_ref (server); */ + server_ref (server); } server_list_free (filtered); @@ -534,6 +548,7 @@ void server_clist_set_list (GSList *servers) { pixmap_cache_clear (&server_pixmap_cache, 8); server_clist_sync_selection (); + debug (7, "server_clist_set_list() -- Done."); } @@ -565,14 +580,17 @@ void server_clist_build_filtered (GSList *server_list, int update) { server = (struct server *) tmp->data; row = gtk_clist_find_row_from_data (server_clist, server); if (row >= 0) { + debug (3, "server_clist_build_filtered() -- Delete server %lx, call gtk_clist_remove()", server); + + /* + Note: Each server clist item gets a server_unref call on + a GtkDestroyNotify event. + */ gtk_clist_remove (server_clist, row); - debug (3, "server_clist_build_filtered() -- Delete server %lx", server); } - /* - Allways unref the server because the list returned - to us had the count incremented by prepend. - */ } + /* Free the list of severs in this loop. */ + debug (7, "server_clist_build_filtered() -- Call server_list_free on [delete] list %lx", delete); server_list_free (delete); } @@ -596,9 +614,11 @@ void server_clist_build_filtered (GSList *server_list, int update) { for (tmp = add; tmp; tmp = tmp->next) { server = (struct server *) tmp->data; row = server_clist_refresh_row (server, -1); + debug (7, "server_clist_build_filtered() -- add server %lx to row %d", server, row); gtk_clist_set_row_data_full (server_clist, row, server, (GtkDestroyNotify) server_unref); - /*server_ref (server);*/ + + server_ref (server); /* See nots above about GtkDestroyNotify */ } server_list_free (add); } diff --git a/xqf/src/stat.c b/xqf/src/stat.c index c3e0ffd..447c41f 100644 --- a/xqf/src/stat.c +++ b/xqf/src/stat.c @@ -448,10 +448,10 @@ static void parse_qstat_record (struct stat_conn *conn) { count as does the prepend below. So we need to decrement it one just for fun. */ - server_unref (server); job->delayed.queued_servers = server_list_prepend (job->delayed.queued_servers, server); job->progress.done++; + server_unref (server); debug (6, "parse_qstat_record() -- Server %lx in delayed list %lx.", server, job->delayed.queued_servers); diff --git a/xqf/src/statistics.c b/xqf/src/statistics.c index 8593e85..0ae67c0 100644 --- a/xqf/src/statistics.c +++ b/xqf/src/statistics.c @@ -165,7 +165,7 @@ static void collect_statistics (void) { enum OS os; enum CPU cpu; - servers = all_servers (); + servers = all_servers (); /* Free at end of this function */ if (servers) { for (tmp = servers; tmp; tmp = tmp->next) { diff --git a/xqf/src/xqf.c b/xqf/src/xqf.c index 0972877..363c6e0 100644 --- a/xqf/src/xqf.c +++ b/xqf/src/xqf.c @@ -409,7 +409,9 @@ static void start_filters_cfg_dialog (GtkWidget *widget, int page_num) { static void update_server_lists_from_selected_source (void) { GSList *cur_masters = NULL; + debug (6, "update_server_lists_from_selected_source() --"); if (cur_server_list) { + debug (6, "update_server_lists_from_selected_source() -- Free cur_server_list %lx", cur_server_list); server_list_free (cur_server_list); cur_server_list = NULL; } @@ -429,7 +431,7 @@ static int stat_lists_refresh (struct stat_job *job) { int items; int freeze; - debug (6, "sta_lists_refresh() -- Job %lx", job); + debug (6, "stat_lists_refresh() -- Job %lx", job); items = g_slist_length (job->delayed.queued_servers) + g_slist_length (job->delayed.queued_hosts); if (items) { @@ -835,6 +837,7 @@ static int server_clist_compare_func (GtkCList *clist, GtkCListRow *row2 = (GtkCListRow *) ptr2; struct server *s1 = (struct server *) row1->data; struct server *s2 = (struct server *) row2->data; + debug (7, "server_clist_compare_func() --"); return compare_servers (s1, s2, clist->sort_column); } @@ -867,6 +870,7 @@ static void update_source_callback (GtkWidget *widget, gpointer data) { GSList *servers = NULL; GSList *uservers = NULL; + debug (6, "update_source_callback() -- "); if (stat_process || !cur_source) return; @@ -925,6 +929,7 @@ static void add_to_favorites_callback (GtkWidget *widget, gpointer data) { char buf[256]; /* if you change this, change the statement below */ int server_list_size; + debug (7, "add_to_favorites_callback() -- "); if (stat_process || !selected) return; @@ -953,6 +958,7 @@ static void add_to_favorites_callback (GtkWidget *widget, gpointer data) { print_status (main_status_bar, buf ); } + debug (7, "add_to_favorites_callback() -- Saving To Favorites"); save_favorites (); server_list_free (list); } @@ -962,6 +968,7 @@ static void add_to_favorites_callback (GtkWidget *widget, gpointer data) { static void add_server_real (struct stat_job *job, struct server *s) { int row; + debug (6, "add_server_real() -- Server %lx", s); favorites->servers = server_list_append (favorites->servers, s); save_favorites (); @@ -1060,6 +1067,7 @@ static void del_server_callback (GtkWidget *widget, gpointer data) { GSList *list; GSList *tmp; + debug (7, "del_server_callback() -- "); if (stat_process || !cur_source || (struct master *) cur_source->data != favorites) { return; @@ -1282,6 +1290,7 @@ static void resolve_callback (GtkWidget *widget, gpointer data) { GSList *hosts; struct server *s; + debug (7, "resolve_callback() --"); if (stat_process) return; @@ -1361,7 +1370,7 @@ static void rcon_callback (GtkWidget *widget, gpointer data) { static void server_clist_select_callback (GtkWidget *widget, int row, int column, GdkEvent *event, GtkWidget *button) { GdkEventButton *bevent = (GdkEventButton *) event; - + debug (7, "server_clist_select_callback() -- Row %d", row); server_clist_sync_selection (); if (bevent && bevent->type == GDK_2BUTTON_PRESS && bevent->button == 1) @@ -1371,6 +1380,7 @@ static void server_clist_select_callback (GtkWidget *widget, int row, static void server_clist_unselect_callback (GtkWidget *widget, int row, int column, GdkEvent *event, GtkWidget *button) { + debug (7, "server_clist_uselect_callback() -- Row %d", row); server_clist_sync_selection (); } @@ -1400,6 +1410,7 @@ static int server_clist_event_callback (GtkWidget *widget, GdkEvent *event) { GList *selection; int row; + /* debug (7, "server_clist_event_callback() -- "); */ if (event->type == GDK_BUTTON_PRESS && bevent->window == server_clist->clist_window) { @@ -1440,6 +1451,7 @@ static void source_selection_changed (void) { GtkCTreeNode *node; struct master *m; + debug (6, "souce_selection_changed() --"); if (cur_source) { g_slist_free (cur_source); cur_source = NULL; @@ -2532,11 +2544,13 @@ int main (int argc, char *argv[]) { stop_callback (NULL, NULL); if (server_menu) { + debug( 6, "EXIT: destroy server_menu"); gtk_widget_destroy (server_menu); server_menu = NULL; } if (player_menu) { + debug( 6, "EXIT: destroy player_menu"); gtk_widget_destroy (player_menu); player_menu = NULL; } @@ -2553,6 +2567,7 @@ int main (int argc, char *argv[]) { filters_done (); props_free_all (); + debug( 6, "EXIT: Free Server Lists"); g_slist_free (cur_source); server_list_free (cur_server_list); userver_list_free (cur_userver_list); @@ -2565,7 +2580,10 @@ int main (int argc, char *argv[]) { host_cache_save (); host_cache_clear (); + debug( 6, "EXIT: Free Master Lists"); free_masters (); + + debug( 6, "EXIT: Call rcon_done."); rcon_done (); psearch_done (); add_server_done (); @@ -2578,7 +2596,7 @@ int main (int argc, char *argv[]) { fprintf (stderr, "total uservers: %d\n", uservers_total ()); fprintf (stderr, "total hosts: %d\n", hosts_total ()); if (servers_total () > 0) { - GSList *list = all_servers (); + GSList *list = all_servers (); /* Debug code, free done in two lines */ server_list_fprintf (stderr, list); server_list_free (list); @@ -2589,6 +2607,7 @@ int main (int argc, char *argv[]) { config_sync (); config_drop_all (); + debug( 6, "EXIT: Done."); return 0; }