/** * Unregister callbacks in the backend and clean up. */ void nodes_gui_shutdown(void) { tree_view_motion_clear_callback(&tvm_nodes); tree_view_save_widths(treeview_nodes, PROP_NODES_COL_WIDTHS); tree_view_save_visibility(treeview_nodes, PROP_NODES_COL_VISIBLE); guc_node_remove_node_added_listener(nodes_gui_node_added); guc_node_remove_node_removed_listener(nodes_gui_node_removed); guc_node_remove_node_info_changed_listener(nodes_gui_node_info_changed); guc_node_remove_node_flags_changed_listener(nodes_gui_node_flags_changed); gtk_list_store_clear(nodes_model); g_object_unref(G_OBJECT(nodes_model)); nodes_model = NULL; gtk_tree_view_set_model(treeview_nodes, NULL); htable_foreach(nodes_handles, free_node_data, NULL); htable_free_null(&nodes_handles); hset_foreach(ht_node_info_changed, free_node_id, NULL); hset_free_null(&ht_node_info_changed); hset_foreach(ht_node_flags_changed, free_node_id, NULL); hset_free_null(&ht_node_flags_changed); hset_foreach(ht_pending_lookups, free_node_id, NULL); hset_free_null(&ht_pending_lookups); }
/** * Remove all entries in the "seen" hashed set. */ static void udp_sched_seen_clear(udp_sched_t *us) { udp_sched_check(us); hset_foreach(us->seen, udp_seen_host_free, NULL); hset_clear(us->seen); }
/** * Called when servent shuts down. */ void gwc_close(void) { int i; gwc_store(); hset_free_null(&gwc_known_url); hset_foreach(gwc_failed_url, free_failed_url, NULL); hset_free_null(&gwc_failed_url); for (i = 0; i < MAX_GWC_URLS; i++) { const char *url = gwc_url[i].url; if (url == NULL) continue; atom_str_free(url); } gwc_clear_current_url(FALSE); }
/** * Recreate keyinfo data from persisted information. */ static G_GNUC_COLD void keys_init_keyinfo(void) { struct keys_create_context ctx; if (GNET_PROPERTY(dht_keys_debug)) { size_t count = dbmw_count(db_keydata); g_debug("DHT KEYS scanning %u persisted key%s", (unsigned) count, plural(count)); } ctx.our_kuid = get_our_kuid(); ctx.dbkeys = hset_create(HASH_KEY_FIXED, sizeof(uint64)); dbmw_foreach_remove(db_keydata, reload_ki, &ctx); if (GNET_PROPERTY(dht_keys_debug)) { size_t count = dbmw_count(db_keydata); g_debug("DHT KEYS kept %u key%s, now loading associated values", (unsigned) count, plural(count)); } /* * FIXME: * Unfortunately, we have to reset the keydata database for each of * the keys we're going to recreate, because the logic adding values * back to the key will fill each of the keydata appropriately, and it * expects the amount of values in the keyinfo and the keydata to match. * * Therefore, we need to rename the old keydata database, open a new one, * write empty keydata values in it, then discard the old keydata if * everything goes well. In case of a crash in the middle of the * restoration, we'll be able to recover by opening the old keydata first * if it exists. * * It is far from critical though: if we reset the keydata database and * we crash in the middle of the restore, then we'll lose all the persisted * keys and values and will simply restart with an empty storage. * * Given the contorsions needed to fix that, and the little value for * the user, just leaving a FIXME note. * --RAM, 2012-11-17 */ hikset_foreach(keys, keys_reset_keydata, NULL); values_init_data(ctx.dbkeys); hset_foreach(ctx.dbkeys, keys_free_dbkey, NULL); hset_free_null(&ctx.dbkeys); hikset_foreach_remove(keys, keys_discard_if_empty, NULL); dbmw_foreach_remove(db_keydata, keys_delete_if_empty, NULL); dbstore_compact(db_keydata); g_soft_assert_log(hikset_count(keys) == dbmw_count(db_keydata), "keys reloaded: %zu, key data persisted: %zu", hikset_count(keys), dbmw_count(db_keydata)); if (GNET_PROPERTY(dht_keys_debug)) { g_debug("DHT KEYS reloaded %zu key%s", hikset_count(keys), plural(hikset_count(keys))); } gnet_stats_set_general(GNR_DHT_KEYS_HELD, hikset_count(keys)); }
/** * Closes all file descriptors greater or equal to ``first_fd'', skipping * preserved ones if ``preserve'' is TRUE. */ static void fd_close_from_internal(const int first_fd, bool preserve) { int fd; g_return_if_fail(first_fd >= 0); if (!preserve && try_close_from(first_fd)) return; fd = getdtablesize() - 1; while (fd >= first_fd) { if (preserve && hset_contains(fd_preserved, int_to_pointer(fd))) goto next; #ifdef HAVE_GTKOSXAPPLICATION /* OS X doesn't allow fds being closed not opened by us. During * GUI initialisation a new kqueue fd is created for UI events. This * is visible to us as a fifo which we are not allowed to close. * Set close on exec on all fifo's so we won't leak any of our other * fifo's * -- JA 2011-11-28 */ if (is_a_fifo(fd)) fd_set_close_on_exec(fd); else #endif /* OS X frowns upon random fds being closed --RAM 2011-11-13 */ if (fd_is_opened(fd)) { if (close(fd)) { #if defined(F_MAXFD) fd = fcntl(0, F_MAXFD); continue; #endif /* F_MAXFD */ } } next: fd--; } /* * When called with a first_fd of 3, and we are on Windows, also make * sure we close all the known sockets we have. This lets the process * safely auto-restart, avoiding multiple listening sockets on the same * port. * --RAM, 2015-04-05 */ if ( is_running_on_mingw() && !preserve && 3 == first_fd && NULL != fd_sockets ) { hset_t *fds = fd_sockets; /* * We're about to exec() another process, and we may be crashing, * hence do not bother using hset_foreach_remove() to ensure minimal * processing. We also reset the fd_sockets pointer to NULL to * make sure s_close() will do nothing when fd_notify_socket_closed() * is called. */ fd_sockets = NULL; /* We don't expect race conditions here */ hset_foreach(fds, fd_socket_close, NULL); /* Don't bother freeing / clearing set, we're about to exec() */ } }