From: Pekka Riikonen Date: Fri, 16 Feb 2007 18:45:34 +0000 (+0000) Subject: Memory leak fixes. X-Git-Tag: silc.client.1.1.beta1~3 X-Git-Url: http://git.silcnet.org/gitweb/?p=silc.git;a=commitdiff_plain;h=c1c904ec2af21f1c2b272d790b38d93824af5352 Memory leak fixes. --- diff --git a/apps/irssi/src/fe-text/silc.c b/apps/irssi/src/fe-text/silc.c index 3de8fdc8..c5f68a8d 100644 --- a/apps/irssi/src/fe-text/silc.c +++ b/apps/irssi/src/fe-text/silc.c @@ -1,7 +1,7 @@ /* irssi.c : irssi - Copyright (C) 1999-2000 Timo Sirainen + Copyright (C) 1999-2000, 2007 Timo Sirainen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -78,21 +78,29 @@ static int dirty, full_redraw, dummy; static GMainLoop *main_loop; int quitting; +int quit_signalled; +int protocols_deinit; -static const char *firsttimer_text = - "Looks like this is the first time you've run irssi.\n" - "This is just a reminder that you really should go read\n" - "startup-HOWTO if you haven't already. You can find it\n" - "and more irssi beginner info at http://irssi.org/help/\n" - "\n" - "For the truly impatient people who don't like any automatic\n" - "window creation or closing, just type: /MANUAL-WINDOWS"; static int display_firsttimer = FALSE; +/* Protocol exit signal to tell protocol has gone away. Safe to quit. */ + +static void sig_protocol_exit(void) +{ + protocols_deinit = TRUE; + if (!quitting && quit_signalled) + quitting = TRUE; +} static void sig_exit(void) { - quitting = TRUE; + quit_signalled = TRUE; + + /* If protocol hasn't finished yet, wait untill it sends "chat protocol + deinit" signal. */ + if (!protocols_deinit) + return; + quitting = TRUE; } /* redraw irssi's screen.. */ @@ -152,11 +160,15 @@ static void textui_init(void) theme_register(gui_text_formats); signal_add_last("gui exit", (SIGNAL_FUNC) sig_exit); + signal_add_last("chat protocol deinit", + (SIGNAL_FUNC) sig_protocol_exit); } static void textui_finish_init(void) { quitting = FALSE; + quit_signalled = FALSE; + protocols_deinit = FALSE; if (dummy) term_dummy_init(); @@ -192,13 +204,6 @@ static void textui_finish_init(void) fe_common_core_finish_init(); signal_emit("irssi init finished", 0); - -#if 0 - if (display_firsttimer) { - printtext_window(active_win, MSGLEVEL_CLIENTNOTICE, - "%s", firsttimer_text); - } -#endif } static void textui_deinit(void) @@ -216,6 +221,7 @@ static void textui_deinit(void) dirty_check(); /* one last time to print any quit messages */ signal_remove("gui exit", (SIGNAL_FUNC) sig_exit); + signal_remove("chat protocol deinit", (SIGNAL_FUNC) sig_protocol_exit); if (dummy) term_dummy_deinit(); @@ -342,6 +348,8 @@ int main(int argc, char **argv) dummy = FALSE; quitting = FALSE; + quit_signalled = FALSE; + protocols_deinit = FALSE; core_init_paths(argc, argv); check_files(); diff --git a/apps/irssi/src/silc/core/client_ops.c b/apps/irssi/src/silc/core/client_ops.c index 5f1ff5d0..ed49b533 100644 --- a/apps/irssi/src/silc/core/client_ops.c +++ b/apps/irssi/src/silc/core/client_ops.c @@ -2348,6 +2348,7 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, if (!pw) { if (completion) completion(FALSE, context); + silc_free(pk); return; } @@ -2429,6 +2430,8 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); return; } else { /* The key already exists, verify it. */ @@ -2453,6 +2456,8 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); return; } @@ -2474,8 +2479,11 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); + silc_free(pk); return; } + silc_pkcs_public_key_free(local_pubkey); /* Compare the keys */ if (memcmp(encpk, pk, encpk_len)) { @@ -2500,7 +2508,9 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, format, 0, verify); g_free(format); silc_free(fingerprint); + silc_free(babbleprint); silc_free(encpk); + silc_free(pk); return; } @@ -2509,10 +2519,12 @@ silc_verify_public_key_internal(SilcClient client, SilcClientConnection conn, completion(TRUE, context); silc_free(encpk); silc_free(fingerprint); + silc_free(babbleprint); silc_free(verify->filename); silc_free(verify->entity); silc_free(verify->entity_name); silc_free(verify); + silc_free(pk); } } diff --git a/apps/irssi/src/silc/core/silc-core.c b/apps/irssi/src/silc/core/silc-core.c index 8c38c5c7..259d7a6f 100644 --- a/apps/irssi/src/silc/core/silc-core.c +++ b/apps/irssi/src/silc/core/silc-core.c @@ -292,8 +292,8 @@ void silc_opt_callback(poptContext con, } if (strcmp(opt->longName, "hostname") == 0) { - g_free(opt_hostname); - opt_hostname = g_strdup(arg); + silc_free(opt_hostname); + opt_hostname = strdup(arg); } if (strcmp(opt->longName, "list-ciphers") == 0) { @@ -372,6 +372,8 @@ silc_stopped(SilcClient client, void *context) SILC_LOG_DEBUG(("Client library has stopped")); if (idletag != -1) g_source_remove(idletag); + signal_emit("chat protocol deinit", 1, + chat_protocol_find("SILC")); } static void sig_gui_quit(SILC_SERVER_REC *server, const char *msg) @@ -404,9 +406,10 @@ static void sig_init_finished(void) } /* Initialize the SILC client */ + opt_hostname = (opt_hostname ? opt_hostname : silc_net_localhost()); if (!silc_client_init(silc_client, settings_get_str("user_name"), - opt_hostname ? opt_hostname : silc_net_localhost(), - settings_get_str("real_name"), silc_running, NULL)) { + opt_hostname, settings_get_str("real_name"), + silc_running, NULL)) { sleep(1); exit(1); return; @@ -564,12 +567,17 @@ void silc_core_deinit(void) if (idletag != -1) g_source_remove(idletag); - signal_emit("chat protocol deinit", 1, - chat_protocol_find("SILC")); + if (opt_hostname) + silc_free(opt_hostname); + if (opt_nickname) + g_free(opt_nickname); + signal_remove("setup changed", (SIGNAL_FUNC) sig_setup_changed); signal_remove("irssi init finished", (SIGNAL_FUNC) sig_init_finished); signal_remove("gui exit", (SIGNAL_FUNC) sig_gui_quit); + silc_hash_free(sha1hash); + silc_queue_deinit(); silc_server_deinit(); silc_channels_deinit(); @@ -580,7 +588,7 @@ void silc_core_deinit(void) chat_protocol_unregister("SILC"); - silc_pkcs_private_key_free(irssi_privkey); silc_pkcs_public_key_free(irssi_pubkey); + silc_pkcs_private_key_free(irssi_privkey); silc_client_free(silc_client); } diff --git a/apps/irssi/src/silc/core/silc-servers.c b/apps/irssi/src/silc/core/silc-servers.c index 38ea4f48..eb70efd5 100644 --- a/apps/irssi/src/silc/core/silc-servers.c +++ b/apps/irssi/src/silc/core/silc-servers.c @@ -423,6 +423,7 @@ static void sig_connected_stream_created(SilcSocketStreamStatus status, if (params.detach_data) printformat_module("fe-common/silc", server, NULL, MSGLEVEL_CRAP, SILCTXT_REATTACH, server->tag); + silc_free(file); /* Start key exchange */ server->op = silc_client_key_exchange(silc_client, ¶ms, diff --git a/lib/silcapputil/silcidcache.h b/lib/silcapputil/silcidcache.h index b9fff272..088dd058 100644 --- a/lib/silcapputil/silcidcache.h +++ b/lib/silcapputil/silcidcache.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2000 - 2006 Pekka Riikonen + Copyright (C) 2000 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -140,11 +140,8 @@ void silc_idcache_free(SilcIDCache cache); * Add new entry to the cache. Returns the allocated cache entry if the * entry was added successfully, or NULL if error occurred. The `name' is * the name associated with the ID, the `id' the actual ID and the - * `context' a caller specific context. - * - * The `name', `id' and `context' pointers will be stored in the cache, - * and if the caller frees these pointers the caller is also responsible - * of deleting the cache entry. + * `context' a caller specific context. The caller is responsible of + * freeing the `name' and `id' when the entry is deleted. * ***/ SilcIDCacheEntry diff --git a/lib/silcclient/client.c b/lib/silcclient/client.c index 0ee9f52a..5eeb6c35 100644 --- a/lib/silcclient/client.c +++ b/lib/silcclient/client.c @@ -731,6 +731,12 @@ void silc_client_del_connection(SilcClient client, SilcClientConnection conn) silc_hash_free(conn->internal->sha1hash); silc_atomic_uninit16(&conn->internal->cmd_ident); + if (conn->internal->rekey) + silc_ske_free_rekey_material(conn->internal->rekey); + + if (conn->internal->cop) + silc_async_free(conn->internal->cop); + silc_free(conn->internal); memset(conn, 'F', sizeof(*conn)); silc_free(conn); @@ -934,7 +940,10 @@ void silc_client_free(SilcClient client) silc_hmac_unregister_all(); } + silc_packet_engine_stop(client->internal->packet_engine); + silc_dlist_uninit(client->internal->ftp_sessions); silc_atomic_uninit16(&client->internal->conns); + silc_mutex_free(client->internal->lock); silc_free(client->username); silc_free(client->hostname); silc_free(client->realname); diff --git a/lib/silcclient/client_connect.c b/lib/silcclient/client_connect.c index f160fb02..06f6a713 100644 --- a/lib/silcclient/client_connect.c +++ b/lib/silcclient/client_connect.c @@ -703,6 +703,9 @@ SILC_FSM_STATE(silc_client_st_connected) conn->callback(client, conn, SILC_CLIENT_CONN_SUCCESS, 0, NULL, conn->callback_context); + silc_async_free(conn->internal->cop); + conn->internal->cop = NULL; + return SILC_FSM_FINISH; } diff --git a/lib/silcclient/client_entry.c b/lib/silcclient/client_entry.c index 18546fb7..ae7cba71 100644 --- a/lib/silcclient/client_entry.c +++ b/lib/silcclient/client_entry.c @@ -1532,6 +1532,7 @@ SilcChannelEntry silc_client_add_channel(SilcClient client, SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn, SilcChannelEntry channel) { + SilcIDCacheEntry id_cache; SilcBool ret; SilcCipher key; SilcHmac hmac; @@ -1545,6 +1546,9 @@ SilcBool silc_client_del_channel(SilcClient client, SilcClientConnection conn, SILC_LOG_DEBUG(("Deleting channel %p", channel)); silc_mutex_lock(conn->internal->lock); + if (silc_idcache_find_by_context(conn->internal->channel_cache, channel, + &id_cache)) + silc_free(id_cache->name); ret = silc_idcache_del_by_context(conn->internal->channel_cache, channel, NULL); silc_mutex_unlock(conn->internal->lock); @@ -1935,6 +1939,7 @@ SilcServerEntry silc_client_add_server(SilcClient client, SilcBool silc_client_del_server(SilcClient client, SilcClientConnection conn, SilcServerEntry server) { + SilcIDCacheEntry id_cache; SilcBool ret; if (!server) @@ -1946,6 +1951,9 @@ SilcBool silc_client_del_server(SilcClient client, SilcClientConnection conn, SILC_LOG_DEBUG(("Deleting server %p", server)); silc_mutex_lock(conn->internal->lock); + if (silc_idcache_find_by_context(conn->internal->server_cache, server, + &id_cache)) + silc_free(id_cache->name); ret = silc_idcache_del_by_context(conn->internal->server_cache, server, NULL); silc_mutex_unlock(conn->internal->lock); diff --git a/lib/silcclient/client_register.c b/lib/silcclient/client_register.c index a2380c80..b021abc6 100644 --- a/lib/silcclient/client_register.c +++ b/lib/silcclient/client_register.c @@ -236,6 +236,8 @@ SILC_FSM_STATE(silc_client_st_register_complete) conn->internal->registering = FALSE; silc_schedule_task_del_by_all(conn->internal->schedule, 0, silc_client_connect_timeout, conn); + silc_async_free(conn->internal->cop); + conn->internal->cop = NULL; return SILC_FSM_FINISH; } @@ -578,6 +580,8 @@ SILC_FSM_STATE(silc_client_st_resume_completed) silc_client_connect_timeout, conn); silc_free(resume->nickname); silc_free(resume); + silc_async_free(conn->internal->cop); + conn->internal->cop = NULL; return SILC_FSM_FINISH; } diff --git a/lib/silccore/silcpacket.c b/lib/silccore/silcpacket.c index 071652bc..94fcffc7 100644 --- a/lib/silccore/silcpacket.c +++ b/lib/silccore/silcpacket.c @@ -604,14 +604,22 @@ silc_packet_engine_start(SilcRng rng, SilcBool router, void silc_packet_engine_stop(SilcPacketEngine engine) { + SilcPacket packet; SILC_LOG_DEBUG(("Stopping packet engine")); if (!engine) return; - /* XXX */ + /* Free packet free list */ + silc_list_start(engine->packet_pool); + while ((packet = silc_list_get(engine->packet_pool))) { + silc_buffer_purge(&packet->buffer); + silc_free(packet); + } + silc_hash_table_free(engine->contexts); + silc_mutex_free(engine->lock); silc_free(engine); } @@ -879,7 +887,27 @@ void silc_packet_stream_destroy(SilcPacketStream stream) silc_dlist_uninit(stream->process); } - /* XXX */ + /* Destroy ciphers and HMACs */ + if (stream->send_key[0]) + silc_cipher_free(stream->send_key[0]); + if (stream->receive_key[0]) + silc_cipher_free(stream->receive_key[0]); + if (stream->send_hmac[0]) + silc_hmac_free(stream->send_hmac[0]); + if (stream->receive_hmac[0]) + silc_hmac_free(stream->receive_hmac[0]); + if (stream->send_key[1]) + silc_cipher_free(stream->send_key[1]); + if (stream->receive_key[1]) + silc_cipher_free(stream->receive_key[1]); + if (stream->send_hmac[1]) + silc_hmac_free(stream->send_hmac[1]); + if (stream->receive_hmac[1]) + silc_hmac_free(stream->receive_hmac[1]); + + /* Free IDs */ + silc_free(stream->src_id); + silc_free(stream->dst_id); silc_atomic_uninit8(&stream->refcnt); silc_mutex_free(stream->lock); @@ -1167,7 +1195,7 @@ SilcBool silc_packet_set_keys(SilcPacketStream stream, SilcCipher send_key, } else { if (stream->send_key[0] && send_key) silc_cipher_free(stream->send_key[0]); - if (stream->send_key[1] && receive_key) + if (stream->receive_key[0] && receive_key) silc_cipher_free(stream->receive_key[0]); if (stream->send_hmac[0] && send_hmac) silc_hmac_free(stream->send_hmac[0]); @@ -2447,7 +2475,7 @@ int silc_packet_wrap_read(SilcStream stream, unsigned char *buf, if (read_more && !pws->blocking) { /* More data will be available (in blocking mode not supported). */ silc_buffer_pull(&packet->buffer, len); - silc_list_insert(pws->in_queue, NULL, packet); + silc_list_insert(pws->in_queue, NULL, packet); silc_schedule_task_add_timeout(pws->stream->sc->schedule, silc_packet_wrap_read_more, pws, 0, 0); pws->read_more = TRUE; diff --git a/lib/silccrypt/silchash.c b/lib/silccrypt/silchash.c index a9729c93..59cdf7f9 100644 --- a/lib/silccrypt/silchash.c +++ b/lib/silccrypt/silchash.c @@ -118,6 +118,7 @@ SilcBool silc_hash_unregister(SilcHashObject *hash) if (hash == SILC_ALL_HASH_FUNCTIONS || entry == hash) { silc_dlist_del(silc_hash_list, entry); silc_free(entry->name); + silc_free(entry->oid); silc_free(entry); if (silc_dlist_count(silc_hash_list) == 0) { diff --git a/lib/silccrypt/silcpkcs.c b/lib/silccrypt/silcpkcs.c index 6bd2eaac..f5ae7873 100644 --- a/lib/silccrypt/silcpkcs.c +++ b/lib/silccrypt/silcpkcs.c @@ -489,6 +489,7 @@ SilcBool silc_pkcs_public_key_alloc(SilcPKCSType type, void silc_pkcs_public_key_free(SilcPublicKey public_key) { public_key->pkcs->public_key_free(public_key->public_key); + silc_free(public_key); } /* Exports public key */ @@ -564,6 +565,7 @@ SilcUInt32 silc_pkcs_private_key_get_len(SilcPrivateKey private_key) void silc_pkcs_private_key_free(SilcPrivateKey private_key) { private_key->pkcs->private_key_free(private_key->private_key); + silc_free(private_key); } /* Encrypts */ diff --git a/lib/silcske/silcconnauth.c b/lib/silcske/silcconnauth.c index 6947095b..b5e59ab5 100644 --- a/lib/silcske/silcconnauth.c +++ b/lib/silcske/silcconnauth.c @@ -32,6 +32,7 @@ static SilcBool silc_connauth_packet_receive(SilcPacketEngine engine, struct SilcConnAuthStruct { SilcSKE ske; SilcFSM fsm; + SilcAsyncOperationStruct op; SilcConnectionType conn_type; SilcAuthMethod auth_method; void *auth_data; @@ -395,8 +396,6 @@ silc_connauth_initiator(SilcConnAuth connauth, SilcConnAuthCompletion completion, void *context) { - SilcAsyncOperation op; - SILC_LOG_DEBUG(("Connection authentication as initiator")); if (auth_method == SILC_AUTH_PASSWORD && !auth_data) { @@ -423,10 +422,10 @@ silc_connauth_initiator(SilcConnAuth connauth, SILC_PACKET_FAILURE, -1); /* Start the protocol */ - op = silc_async_alloc(silc_connauth_abort, NULL, connauth); + silc_async_init(&connauth->op, silc_connauth_abort, NULL, connauth); silc_fsm_start(connauth->fsm, silc_connauth_st_initiator_start); - return op; + return &connauth->op; } @@ -684,8 +683,6 @@ silc_connauth_responder(SilcConnAuth connauth, SilcConnAuthCompletion completion, void *context) { - SilcAsyncOperation op; - SILC_LOG_DEBUG(("Connection authentication as responder")); connauth->get_auth_data = get_auth_data; @@ -699,8 +696,8 @@ silc_connauth_responder(SilcConnAuth connauth, SILC_PACKET_FAILURE, -1); /* Start the protocol */ - op = silc_async_alloc(silc_connauth_abort, NULL, connauth); + silc_async_init(&connauth->op, silc_connauth_abort, NULL, connauth); silc_fsm_start(connauth->fsm, silc_connauth_st_responder_start); - return op; + return &connauth->op; } diff --git a/lib/silcske/silcske.c b/lib/silcske/silcske.c index 0a321b9e..33ec0cdf 100644 --- a/lib/silcske/silcske.c +++ b/lib/silcske/silcske.c @@ -111,7 +111,7 @@ static SilcBool silc_ske_packet_receive(SilcPacketEngine engine, } /* Handle rekey and SUCCESS packets synchronously. After SUCCESS packets - they keys are taken into use immediately, hence the synchronous + they keys are taken into use immediately, hence the synchronous processing to get the keys in use as soon as possible. */ if (ske->rekeying || packet->type == SILC_PACKET_SUCCESS) silc_fsm_continue_sync(&ske->fsm); @@ -1085,6 +1085,8 @@ void silc_ske_free(SilcSKE ske) silc_hash_free(ske->prop->hash); if (ske->prop->hmac) silc_hmac_free(ske->prop->hmac); + if (ske->prop->public_key) + silc_pkcs_public_key_free(ske->prop->public_key); silc_free(ske->prop); } if (ske->keymat) diff --git a/lib/silcutil/silcasync.h b/lib/silcutil/silcasync.h index 773dd059..2853e9c3 100644 --- a/lib/silcutil/silcasync.h +++ b/lib/silcutil/silcasync.h @@ -4,7 +4,7 @@ Author: Pekka Riikonen - Copyright (C) 2005 Pekka Riikonen + Copyright (C) 2005 - 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -101,8 +101,8 @@ typedef void (*SilcAsyncOperationAbort)(SilcAsyncOperation op, * SYNOPSIS * * typedef SilcBool (*SilcAsyncOperationPause)(SilcAsyncOperation op, - * SilcBool pause_operation, - * void *context); + * SilcBool pause_operation, + * void *context); * * DESCRIPTION * @@ -240,9 +240,9 @@ SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb, * SYNOPSIS * * SilcBool silc_async_init(SilcAsyncOperation op, - * SilcAsyncOperationAbort abort_cb, - * SilcAsyncOperationPause pause_cb, - * void *context); + * SilcAsyncOperationAbort abort_cb, + * SilcAsyncOperationPause pause_cb, + * void *context); * * DESCRIPTION * @@ -251,7 +251,8 @@ SilcAsyncOperation silc_async_alloc(SilcAsyncOperationAbort abort_cb, * layer to abort the asynchronous operation, by calling the * silc_async_abort. Since this use pre-allocated context, the function * silc_async_free need not be called. This function is equivalent - * to silc_async_alloc except this does not allocate any memory. + * to silc_async_alloc except this does not allocate any memory. The `op' + * needs not be uninitialized. * * If the `pause_cb' is provided then the upper layer may also halt and * then later resume the execution of the operation, by calling the diff --git a/lib/silcutil/stacktrace.c b/lib/silcutil/stacktrace.c index 2174080c..1eecca1d 100644 --- a/lib/silcutil/stacktrace.c +++ b/lib/silcutil/stacktrace.c @@ -1,10 +1,10 @@ /* - stacktrace.c + stacktrace.c Author: Pekka Riikonen - Copyright (C) 2002 Pekka Riikonen + Copyright (C) 2002, 2007 Pekka Riikonen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,7 +26,11 @@ static unsigned long st_blocks_count = 0; static SilcBool dump = FALSE; static SilcBool malloc_check = FALSE; -#define SILC_ST_DEPTH 10 +#ifdef SILC_DEBUG +#define SILC_ST_DEPTH 15 +#else +#define SILC_ST_DEPTH 8 +#endif /* SILC_DEBUG */ /* Memory block with stack trace */ typedef struct SilcStBlockStruct { @@ -191,7 +195,7 @@ void silc_st_dump(void) for (s = stack; s; s = s->next) { if (s->file == stack->file && s->line == stack->line && s->depth == stack->depth && - !memcmp(s->stack, stack->stack, + !memcmp(s->stack, stack->stack, (s->depth * sizeof(stack->stack[0])))) { blocks++; bytes += s->size; @@ -210,7 +214,7 @@ void silc_st_dump(void) if (!leaks) { fprintf(stderr, "\nNo memory leaks\n"); } else { - fprintf(stderr, + fprintf(stderr, "-----------------------------------------\n" "-----------------------------------------\n" " Memory leaks dumped to 'stacktrace.log'\n"