From 271cf23083b38b3f0d12a36bb1f28e458ee43861 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 21 Nov 2006 12:39:31 +0000 Subject: Fixed handles leak upon program exit, by introducing pj_shutdown() and pj_atexit(). Also fixed handle leaks in SIP transaction layer and SIP endpoint. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@815 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/src/pj/except.c | 9 ++++++++ pjlib/src/pj/os_core_unix.c | 51 ++++++++++++++++++++++++++++++++++++++------ pjlib/src/pj/os_core_win32.c | 51 ++++++++++++++++++++++++++++++++++++++++++-- pjlib/src/pj/pool_buf.c | 16 +++++++++++--- 4 files changed, 115 insertions(+), 12 deletions(-) (limited to 'pjlib/src') diff --git a/pjlib/src/pj/except.c b/pjlib/src/pj/except.c index 1074828f..bb21e05b 100644 --- a/pjlib/src/pj/except.c +++ b/pjlib/src/pj/except.c @@ -51,6 +51,14 @@ PJ_DEF(void) pj_throw_exception_(int exception_id) pj_longjmp(handler->state, exception_id); } +static void exception_cleanup(void) +{ + if (thread_local_id != -1) { + pj_thread_local_free(thread_local_id); + thread_local_id = -1; + } +} + PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec) { struct pj_exception_state_t *parent_handler = NULL; @@ -58,6 +66,7 @@ PJ_DEF(void) pj_push_exception_handler_(struct pj_exception_state_t *rec) if (thread_local_id == -1) { pj_thread_local_alloc(&thread_local_id); pj_assert(thread_local_id != -1); + pj_atexit(&exception_cleanup); } parent_handler = pj_thread_local_get(thread_local_id); rec->prev = parent_handler; diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c index a65c8e89..db55062b 100644 --- a/pjlib/src/pj/os_core_unix.c +++ b/pjlib/src/pj/os_core_unix.c @@ -147,13 +147,6 @@ PJ_DEF(pj_status_t) pj_init(void) guid.ptr = dummy_guid; pj_generate_unique_string( &guid ); - /* Initialize exception ID for the pool. - * Must do so after critical section is configured. - */ - rc = pj_exception_id_alloc("PJLIB/No memory", &PJ_NO_MEMORY_EXCEPTION); - if (rc != PJ_SUCCESS) - return rc; - /* Startup timestamp */ #if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0 { @@ -170,6 +163,50 @@ PJ_DEF(pj_status_t) pj_init(void) return PJ_SUCCESS; } +/* + * pj_atexit() + */ +PJ_DEF(pj_status_t) pj_atexit(void (*func)(void)) +{ + if (atexit_count >= PJ_ARRAY_SIZE(atexit_func)) + return PJ_ETOOMANY; + + atexit_func[atexit_count++] = func; + return PJ_SUCCESS; +} + +/* + * pj_shutdown(void) + */ +PJ_DEF(void) pj_shutdown() +{ + int i; + + /* Call atexit() functions */ + for (i=atexit_count-1; i>=0; --i) { + (*atexit_func[i])(); + } + atexit_count = 0; + + /* Free exception ID */ + if (PJ_NO_MEMORY_EXCEPTION != -1) { + pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION); + PJ_NO_MEMORY_EXCEPTION = -1; + } + +#if PJ_HAS_THREADS + /* Destroy PJLIB critical section */ + pj_mutex_destroy(&critical_section); + + /* Free PJLIB TLS */ + if (thread_tls_id != -1) { + pj_thread_local_free(thread_tls_id); + thread_tls_id = -1; + } +#endif +} + + /* * pj_getpid(void) */ diff --git a/pjlib/src/pj/os_core_win32.c b/pjlib/src/pj/os_core_win32.c index 27091cc6..ea2c8d94 100644 --- a/pjlib/src/pj/os_core_win32.c +++ b/pjlib/src/pj/os_core_win32.c @@ -108,9 +108,10 @@ struct pj_atomic_t * Static global variables. */ static pj_thread_desc main_thread; -static long thread_tls_id; +static long thread_tls_id = -1; static pj_mutex_t critical_section_mutex; - +static unsigned atexit_count; +static void (*atexit_func[32])(void); /* * Some static prototypes. @@ -176,6 +177,52 @@ PJ_DEF(pj_status_t) pj_init(void) return PJ_SUCCESS; } +/* + * pj_atexit() + */ +PJ_DEF(pj_status_t) pj_atexit(void (*func)(void)) +{ + if (atexit_count >= PJ_ARRAY_SIZE(atexit_func)) + return PJ_ETOOMANY; + + atexit_func[atexit_count++] = func; + return PJ_SUCCESS; +} + + +/* + * pj_shutdown(void) + */ +PJ_DEF(void) pj_shutdown() +{ + int i; + + /* Call atexit() functions */ + for (i=atexit_count-1; i>=0; --i) { + (*atexit_func[i])(); + } + atexit_count = 0; + + /* Free exception ID */ + if (PJ_NO_MEMORY_EXCEPTION != -1) { + pj_exception_id_free(PJ_NO_MEMORY_EXCEPTION); + PJ_NO_MEMORY_EXCEPTION = -1; + } + + /* Destroy PJLIB critical section */ + pj_mutex_destroy(&critical_section_mutex); + + /* Free PJLIB TLS */ + if (thread_tls_id != -1) { + pj_thread_local_free(thread_tls_id); + thread_tls_id = -1; + } + + /* Shutdown Winsock */ + WSACleanup(); +} + + /* * pj_getpid(void) */ diff --git a/pjlib/src/pj/pool_buf.c b/pjlib/src/pj/pool_buf.c index 0da6c5e1..44115f3a 100644 --- a/pjlib/src/pj/pool_buf.c +++ b/pjlib/src/pj/pool_buf.c @@ -29,11 +29,21 @@ struct creation_param }; static int is_initialized; -static long tls; +static long tls = -1; static void* stack_alloc(pj_pool_factory *factory, pj_size_t size); -static pj_status_t initialize() +static void pool_buf_cleanup(void) { + if (tls != -1) { + pj_thread_local_free(tls); + tls = -1; + } +} + +static pj_status_t pool_buf_initialize() +{ + pj_atexit(&pool_buf_cleanup); + stack_based_factory.policy.block_alloc = &stack_alloc; return pj_thread_local_alloc(&tls); } @@ -64,7 +74,7 @@ PJ_DEF(pj_pool_t*) pj_pool_create_on_buf(const char *name, PJ_ASSERT_RETURN(buf && size, NULL); if (!is_initialized) { - if (initialize() != PJ_SUCCESS) + if (pool_buf_initialize() != PJ_SUCCESS) return NULL; is_initialized = 1; } -- cgit v1.2.3