From d106ecdc6541c2081c4f2fa9b670e984a79a6326 Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 04:10:42 +0200 Subject: [PATCH 1/3] Bugfixes for pthreads. --- src/util/threads.c | 24 ++++++++++++++++-------- src/util/threads.h | 2 +- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/util/threads.c b/src/util/threads.c index 814037f..b76ef91 100644 --- a/src/util/threads.c +++ b/src/util/threads.c @@ -20,6 +20,12 @@ #include "uhub.h" #ifdef POSIX_THREAD_SUPPORT + +struct pthread_data +{ + pthread_t handle; +}; + void uhub_mutex_init(uhub_mutex_t* mutex) { pthread_mutex_init(mutex, NULL); @@ -48,23 +54,25 @@ int uhub_mutex_trylock(uhub_mutex_t* mutex) uhub_thread_t* uhub_thread_create(uhub_thread_start start, void* arg) { - uhub_thread_t* thread = (uhub_thread_t*) hub_malloc_zero(sizeof(uhub_thread_t)); - int ret = pthread_create(thread, NULL, start, arg); - if (ret == 0) - return thread; - hub_free(thread); - return NULL; + struct pthread_data* thread = (struct pthread_data*) hub_malloc_zero(sizeof(struct pthread_data)); + int ret = pthread_create(&thread->handle, NULL, start, arg); + if (ret != 0) + { + hub_free(thread); + thread = NULL; + } + return thread; } void uhub_thread_cancel(uhub_thread_t* thread) { - pthread_cancel(thread); + pthread_cancel(thread->handle); } void* uhub_thread_join(uhub_thread_t* thread) { void* ret = NULL; - pthread_join(thread, &ret); + pthread_join(thread->handle, &ret); hub_free(thread); return ret; } diff --git a/src/util/threads.h b/src/util/threads.h index afc4359..0e4a9ac 100644 --- a/src/util/threads.h +++ b/src/util/threads.h @@ -23,7 +23,7 @@ typedef void*(*uhub_thread_start)(void*) ; #ifdef POSIX_THREAD_SUPPORT -typedef pthread_t uhub_thread_t; +typedef struct pthread_data uhub_thread_t; typedef pthread_mutex_t uhub_mutex_t; #endif From 38b19f633d5edd4b4458348a9359b846fc51d9ab Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 04:13:05 +0200 Subject: [PATCH 2/3] Fix memory leaks and report "host is not found" correctly. --- src/network/dnsresolver.c | 94 ++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 36 deletions(-) diff --git a/src/network/dnsresolver.c b/src/network/dnsresolver.c index 1d5c597..65a4465 100644 --- a/src/network/dnsresolver.c +++ b/src/network/dnsresolver.c @@ -19,9 +19,6 @@ #include "uhub.h" -// #define DEBUG_LOOKUP_TIME 1 -#define MAX_CONCURRENT_JOBS 25 - static struct net_dns_job* find_and_remove_job(struct net_dns_job* job); static struct net_dns_result* find_and_remove_result(struct net_dns_job* job); @@ -56,6 +53,22 @@ static void free_job(struct net_dns_job* job) } } +static void shutdown_free_jobs(void* ptr) +{ + struct net_dns_job* job = (struct net_dns_job*) ptr; + uhub_thread_cancel(job->thread_handle); + uhub_thread_join(job->thread_handle); + free_job(job); +} + +static void shutdown_free_results(void* ptr) +{ + struct net_dns_result* result = (struct net_dns_result*) ptr; + uhub_thread_join(result->job->thread_handle); + net_dns_result_free(result); +} + + // NOTE: Any job manipulating the members of this // struct must lock the mutex! struct net_dns_subsystem @@ -79,19 +92,21 @@ void net_dns_initialize() void net_dns_destroy() { struct net_dns_job* job; + struct net_dns_result* result; + uhub_mutex_lock(&g_dns->mutex); LOG_TRACE("net_dns_destroy(): jobs=%d", (int) list_size(g_dns->jobs)); - job = (struct net_dns_job*) list_get_first(g_dns->jobs); + list_clear(g_dns->jobs, &shutdown_free_jobs); + + LOG_TRACE("net_dns_destroy(): results=%d", (int) list_size(g_dns->results)); + list_clear(g_dns->results, &shutdown_free_results); uhub_mutex_unlock(&g_dns->mutex); - while (job) - { - net_dns_job_cancel(job); - - uhub_mutex_lock(&g_dns->mutex); - job = (struct net_dns_job*) list_get_first(g_dns->jobs); - uhub_mutex_unlock(&g_dns->mutex); - } + list_destroy(g_dns->jobs); + list_destroy(g_dns->results); + uhub_mutex_destroy(&g_dns->mutex); + hub_free(g_dns); + g_dns = NULL; } static void dummy_free(void* ptr) @@ -149,9 +164,9 @@ static void* job_thread_resolve_name(void* ptr) hints.ai_protocol = IPPROTO_TCP; ret = getaddrinfo(job->host, NULL, &hints, &result); - if (ret != 0) + if (ret != 0 && ret != EAI_NONAME) { - LOG_WARN("getaddrinfo() failed: %s", gai_strerror(ret)); + LOG_TRACE("getaddrinfo() failed: %s", gai_strerror(ret)); return NULL; } @@ -159,32 +174,39 @@ static void* job_thread_resolve_name(void* ptr) dns_results->addr_list = list_create(); dns_results->job = job; - for (it = result; it; it = it->ai_next) + if (ret != EAI_NONAME) { - struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap)); - ipaddr->af = it->ai_family; + for (it = result; it; it = it->ai_next) + { + struct ip_addr_encap* ipaddr = hub_malloc_zero(sizeof(struct ip_addr_encap)); + ipaddr->af = it->ai_family; - if (it->ai_family == AF_INET) - { - struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr; - memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr)); - } - else if (it->ai_family == AF_INET6) - { - struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr; - memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr)); - } - else - { - LOG_WARN("getaddrinfo() returned result with unknown address family: %d", it->ai_family); - hub_free(ipaddr); - continue; - } + if (it->ai_family == AF_INET) + { + struct sockaddr_in* addr4 = (struct sockaddr_in*) it->ai_addr; + memcpy(&ipaddr->internal_ip_data.in, &addr4->sin_addr, sizeof(struct in_addr)); + } + else if (it->ai_family == AF_INET6) + { + struct sockaddr_in6* addr6 = (struct sockaddr_in6*) it->ai_addr; + memcpy(&ipaddr->internal_ip_data.in6, &addr6->sin6_addr, sizeof(struct in6_addr)); + } + else + { + LOG_TRACE("getaddrinfo() returned result with unknown address family: %d", it->ai_family); + hub_free(ipaddr); + continue; + } - LOG_WARN("getaddrinfo() - Address (%d): %s", ret++, ip_convert_to_string(ipaddr)); - list_append(dns_results->addr_list, ipaddr); + LOG_DUMP("getaddrinfo() - Address (%d) %s for \"%s\"", ret++, ip_convert_to_string(ipaddr), job->host); + list_append(dns_results->addr_list, ipaddr); + } + freeaddrinfo(result); + } + else + { + /* hm */ } - freeaddrinfo(result); #ifdef DEBUG_LOOKUP_TIME gettimeofday(&job->time_finish, NULL); From d4763e54db91a69fe58f12c70937a894fd52a47c Mon Sep 17 00:00:00 2001 From: Jan Vidar Krey Date: Thu, 25 Oct 2012 04:13:45 +0200 Subject: [PATCH 3/3] Fixed memory leaks. --- src/tools/adcclient.c | 26 +++++++++++------ src/tools/admin.c | 67 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 83 insertions(+), 10 deletions(-) diff --git a/src/tools/adcclient.c b/src/tools/adcclient.c index b7458e8..6e8f210 100644 --- a/src/tools/adcclient.c +++ b/src/tools/adcclient.c @@ -508,6 +508,7 @@ void ADC_client_send_info(struct ADC_client* client) ADC_TRACE; client->info = adc_msg_construct_source(ADC_CMD_BINF, client->sid, 96); + adc_msg_add_named_argument_string(client->info, ADC_INF_FLAG_NICK, client->nick); if (client->desc) @@ -528,6 +529,7 @@ void ADC_client_send_info(struct ADC_client* client) adc_msg_add_named_argument_int(client->info, ADC_INF_FLAG_UPLOAD_SPEED, 10 * 1024 * 1024); adc_cid_pid(client); + ADC_client_send(client, client->info); } @@ -565,6 +567,7 @@ void ADC_client_destroy(struct ADC_client* client) hub_free(client->nick); hub_free(client->desc); hub_free(client->address.hostname); + hub_free(client); } int ADC_client_connect(struct ADC_client* client, const char* address) @@ -577,19 +580,20 @@ int ADC_client_connect(struct ADC_client* client, const char* address) return 0; return 1; } - else if (client->state == ps_dns) + return ADC_client_connect_internal(client); +} + +int ADC_client_connect_internal(struct ADC_client* client) +{ + int ret; + if (client->state == ps_dns) { // Done name resolving! client->callback(client, ADC_CLIENT_CONNECTING, 0); ADC_client_set_state(client, ps_conn); } - return ADC_client_connect_internal(client); -} - -int ADC_client_connect_internal(struct ADC_client* client) -{ - int ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in)); + ret = net_connect(net_con_get_sd(client->con), (struct sockaddr*) &client->addr, sizeof(struct sockaddr_in)); if (ret == 0 || (ret == -1 && net_error() == EISCONN)) { ADC_client_on_connected(client); @@ -622,10 +626,12 @@ static void ADC_client_on_connected(struct ADC_client* client) else #endif { + struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE); net_con_update(client->con, NET_EVENT_READ); client->callback(client, ADC_CLIENT_CONNECTED, 0); - ADC_client_send(client, adc_msg_create(ADC_HANDSHAKE)); + ADC_client_send(client, handshake); ADC_client_set_state(client, ps_protocol); + adc_msg_free(handshake); } } @@ -633,11 +639,13 @@ static void ADC_client_on_connected(struct ADC_client* client) static void ADC_client_on_connected_ssl(struct ADC_client* client) { ADC_TRACE; + struct adc_message* handshake = adc_msg_create(ADC_HANDSHAKE); client->callback(client, ADC_CLIENT_SSL_OK, 0); client->callback(client, ADC_CLIENT_CONNECTED, 0); net_con_update(client->con, NET_EVENT_READ); - ADC_client_send(client, adc_msg_create(ADC_HANDSHAKE)); + ADC_client_send(client, handshake); ADC_client_set_state(client, ps_protocol); + adc_msg_free(handshake); } #endif diff --git a/src/tools/admin.c b/src/tools/admin.c index 0464dcb..3709368 100644 --- a/src/tools/admin.c +++ b/src/tools/admin.c @@ -35,7 +35,6 @@ static struct ADC_user* user_get(sid_t sid) return user; } - static void user_remove(const struct ADC_client_quit_reason* quit) { struct ADC_user* user = user_get(quit->sid); @@ -162,6 +161,68 @@ static int handle(struct ADC_client* client, enum ADC_client_callback_type type, static int running = 1; +#if !defined(WIN32) +void adm_handle_signal(int sig) +{ + switch (sig) + { + case SIGINT: + LOG_INFO("Interrupted. Shutting down..."); + running = 0; + break; + + case SIGTERM: + LOG_INFO("Terminated. Shutting down..."); + running = 0; + break; + + case SIGPIPE: + break; + + case SIGHUP: + break; + + default: + LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal); + running = 0; + break; + } +} + +static int signals[] = +{ + SIGINT, /* Interrupt the application */ + SIGTERM, /* Terminate the application */ + SIGPIPE, /* prevent sigpipe from kills the application */ + SIGHUP, /* reload configuration */ + 0 +}; + +void adm_setup_signal_handlers() +{ + sigset_t sig_set; + struct sigaction act; + int i; + + sigemptyset(&sig_set); + act.sa_mask = sig_set; + act.sa_flags = SA_ONSTACK | SA_RESTART; + act.sa_handler = adm_handle_signal; + + for (i = 0; signals[i]; i++) + { + if (sigaction(signals[i], &act, 0) != 0) + { + LOG_ERROR("Error setting signal handler %d", signals[i]); + } + } +} + +void adm_shutdown_signal_handlers() +{ +} +#endif /* !WIN32 */ + int main(int argc, char** argv) { if (argc < 2) @@ -170,6 +231,9 @@ int main(int argc, char** argv) return 1; } + hub_set_log_verbosity(5); + adm_setup_signal_handlers(); + struct ADC_client* client; net_initialize(); @@ -183,6 +247,7 @@ int main(int argc, char** argv) ADC_client_destroy(client); net_destroy(); + adm_shutdown_signal_handlers(); return 0; }