summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2012-03-22 11:29:20 +0000
committerNanang Izzuddin <nanang@teluu.com>2012-03-22 11:29:20 +0000
commit759520a6f180a638027fdc7be58e12772247fe47 (patch)
tree4f070ee1947464a3a2ec66b875796f1b76aa1470
parent6496121f32e986850b48f6d5637e21ccddb1bb22 (diff)
Close #1466 (using PJLIB outside PJSUA-LIB context):
- static reference counter for PJLIB init/shutdown. - implemented atexit() in PJMEDIA and PJSIP level: pjmedia_endpt_atexit() & pjsip_endpt_atexit(). - updated pjmedia/transport_srtp.c, pjsip/sip_timer.c, and pjsip/sip_replaces.c to use the new atexit() functions. - API change: pjmedia_srtp_init_lib() now requires 'pjmedia_endpt' param. git-svn-id: http://svn.pjsip.org/repos/pjproject/branches/1.x@3986 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjlib/src/pj/os_core_symbian.cpp20
-rw-r--r--pjlib/src/pj/os_core_unix.c20
-rw-r--r--pjlib/src/pj/os_core_win32.c20
-rw-r--r--pjmedia/include/pjmedia/endpoint.h20
-rw-r--r--pjmedia/include/pjmedia/transport_srtp.h6
-rw-r--r--pjmedia/src/pjmedia/endpoint.c43
-rw-r--r--pjmedia/src/pjmedia/transport_srtp.c20
-rw-r--r--pjsip/include/pjsip/sip_endpoint.h19
-rw-r--r--pjsip/src/pjsip-ua/sip_replaces.c7
-rw-r--r--pjsip/src/pjsip-ua/sip_timer.c6
-rw-r--r--pjsip/src/pjsip/sip_endpoint.c40
-rw-r--r--pjsip/src/pjsua-lib/pjsua_media.c4
12 files changed, 211 insertions, 14 deletions
diff --git a/pjlib/src/pj/os_core_symbian.cpp b/pjlib/src/pj/os_core_symbian.cpp
index abf01b85..52733560 100644
--- a/pjlib/src/pj/os_core_symbian.cpp
+++ b/pjlib/src/pj/os_core_symbian.cpp
@@ -75,6 +75,9 @@ struct pj_sem_t
int max;
};
+/* Flag and reference counter for PJLIB instance */
+static int initialized;
+
/* Flags to indicate which TLS variables have been used */
static int tls_vars[PJ_MAX_TLS];
@@ -83,8 +86,6 @@ static unsigned atexit_count;
static void (*atexit_func[32])(void);
-
-
/////////////////////////////////////////////////////////////////////////////
//
// CPjTimeoutTimer implementation
@@ -335,6 +336,12 @@ PJ_DEF(pj_status_t) pj_init(void)
char stack_ptr;
pj_status_t status;
+ /* Check if PJLIB have been initialized */
+ if (initialized) {
+ ++initialized;
+ return PJ_SUCCESS;
+ }
+
pj_ansi_strcpy(main_thread.obj_name, "pjthread");
// Init main thread
@@ -368,6 +375,10 @@ PJ_DEF(pj_status_t) pj_init(void)
stack_ptr = '\0';
#endif
+ /* Flag PJLIB as initialized */
+ ++initialized;
+ pj_assert(initialized == 1);
+
PJ_LOG(5,(THIS_FILE, "PJLIB initialized."));
return PJ_SUCCESS;
@@ -390,6 +401,11 @@ PJ_DEF(pj_status_t) pj_atexit(pj_exit_callback func)
PJ_DEF(void) pj_shutdown(void)
{
+ /* Only perform shutdown operation when 'initialized' reaches zero */
+ pj_assert(initialized > 0);
+ if (--initialized != 0)
+ return;
+
/* Call atexit() functions */
while (atexit_count > 0) {
(*atexit_func[atexit_count-1])();
diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c
index 3fcfa565..00087b64 100644
--- a/pjlib/src/pj/os_core_unix.c
+++ b/pjlib/src/pj/os_core_unix.c
@@ -102,6 +102,11 @@ struct pj_event_t
#endif /* PJ_HAS_EVENT_OBJ */
+/*
+ * Flag and reference counter for PJLIB instance.
+ */
+static int initialized;
+
#if PJ_HAS_THREADS
static pj_thread_t main_thread;
static long thread_tls_id;
@@ -127,6 +132,12 @@ PJ_DEF(pj_status_t) pj_init(void)
pj_str_t guid;
pj_status_t rc;
+ /* Check if PJLIB have been initialized */
+ if (initialized) {
+ ++initialized;
+ return PJ_SUCCESS;
+ }
+
#if PJ_HAS_THREADS
/* Init this thread's TLS. */
if ((rc=pj_thread_init()) != 0) {
@@ -167,6 +178,10 @@ PJ_DEF(pj_status_t) pj_init(void)
}
#endif
+ /* Flag PJLIB as initialized */
+ ++initialized;
+ pj_assert(initialized == 1);
+
PJ_LOG(4,(THIS_FILE, "pjlib %s for POSIX initialized",
PJ_VERSION));
@@ -192,6 +207,11 @@ PJ_DEF(void) pj_shutdown()
{
int i;
+ /* Only perform shutdown operation when 'initialized' reaches zero */
+ pj_assert(initialized > 0);
+ if (--initialized != 0)
+ return;
+
/* Call atexit() functions */
for (i=atexit_count-1; i>=0; --i) {
(*atexit_func[i])();
diff --git a/pjlib/src/pj/os_core_win32.c b/pjlib/src/pj/os_core_win32.c
index 2b7c2c91..55d7b1b9 100644
--- a/pjlib/src/pj/os_core_win32.c
+++ b/pjlib/src/pj/os_core_win32.c
@@ -117,6 +117,11 @@ struct pj_atomic_t
};
/*
+ * Flag and reference counter for PJLIB instance.
+ */
+static int initialized;
+
+/*
* Static global variables.
*/
static pj_thread_desc main_thread;
@@ -142,6 +147,12 @@ PJ_DEF(pj_status_t) pj_init(void)
pj_str_t guid;
pj_status_t rc;
+ /* Check if PJLIB have been initialized */
+ if (initialized) {
+ ++initialized;
+ return PJ_SUCCESS;
+ }
+
/* Init Winsock.. */
if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
return PJ_RETURN_OS_ERROR(WSAGetLastError());
@@ -187,6 +198,10 @@ PJ_DEF(pj_status_t) pj_init(void)
}
#endif
+ /* Flag PJLIB as initialized */
+ ++initialized;
+ pj_assert(initialized == 1);
+
PJ_LOG(4,(THIS_FILE, "pjlib %s for win32 initialized",
PJ_VERSION));
@@ -213,6 +228,11 @@ PJ_DEF(void) pj_shutdown()
{
int i;
+ /* Only perform shutdown operation when 'initialized' reaches zero */
+ pj_assert(initialized > 0);
+ if (--initialized != 0)
+ return;
+
/* Display stack usage */
#if defined(PJ_OS_HAS_CHECK_STACK) && PJ_OS_HAS_CHECK_STACK!=0
{
diff --git a/pjmedia/include/pjmedia/endpoint.h b/pjmedia/include/pjmedia/endpoint.h
index 37778b7a..2455bcea 100644
--- a/pjmedia/include/pjmedia/endpoint.h
+++ b/pjmedia/include/pjmedia/endpoint.h
@@ -60,6 +60,12 @@ typedef enum pjmedia_endpt_flag
/**
+ * Type of callback to register to pjmedia_endpt_atexit().
+ */
+typedef void (*pjmedia_endpt_exit_callback)(pjmedia_endpt *endpt);
+
+
+/**
* Create an instance of media endpoint.
*
* @param pf Pool factory, which will be used by the media endpoint
@@ -204,6 +210,20 @@ PJ_DECL(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt,
PJ_DECL(pj_status_t) pjmedia_endpt_dump(pjmedia_endpt *endpt);
+/**
+ * Register cleanup function to be called by media endpoint when
+ * #pjmedia_endpt_destroy() is called.
+ *
+ * @param endpt The media endpoint.
+ * @param func The function to be registered.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_endpt_atexit(pjmedia_endpt *endpt,
+ pjmedia_endpt_exit_callback func);
+
+
+
PJ_END_DECL
diff --git a/pjmedia/include/pjmedia/transport_srtp.h b/pjmedia/include/pjmedia/transport_srtp.h
index 3a4820e8..910ec1d0 100644
--- a/pjmedia/include/pjmedia/transport_srtp.h
+++ b/pjmedia/include/pjmedia/transport_srtp.h
@@ -200,8 +200,12 @@ typedef struct pjmedia_srtp_info
* will also invoke this function. This function will also register SRTP
* library deinitialization to #pj_atexit(), so the deinitialization
* of SRTP library will be performed automatically by PJLIB destructor.
+ *
+ * @param endpt The media endpoint instance.
+ *
+ * @return PJ_SUCCESS on success.
*/
-PJ_DECL(pj_status_t) pjmedia_srtp_init_lib(void);
+PJ_DECL(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt);
/**
diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c
index a9adfc2b..43ed4ccf 100644
--- a/pjmedia/src/pjmedia/endpoint.c
+++ b/pjmedia/src/pjmedia/endpoint.c
@@ -23,6 +23,7 @@
#include <pjmedia-audiodev/audiodev.h>
#include <pj/assert.h>
#include <pj/ioqueue.h>
+#include <pj/lock.h>
#include <pj/log.h>
#include <pj/os.h>
#include <pj/pool.h>
@@ -56,6 +57,14 @@ static int PJ_THREAD_FUNC worker_proc(void*);
#define MAX_THREADS 16
+/* List of media endpoint exit callback. */
+typedef struct exit_cb
+{
+ PJ_DECL_LIST_MEMBER (struct exit_cb);
+ pjmedia_endpt_exit_callback func;
+} exit_cb;
+
+
/** Concrete declaration of media endpoint. */
struct pjmedia_endpt
{
@@ -85,6 +94,9 @@ struct pjmedia_endpt
/** Is telephone-event enable */
pj_bool_t has_telephone_event;
+
+ /** List of exit callback. */
+ exit_cb exit_cb_list;
};
/**
@@ -128,6 +140,9 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf,
if (status != PJ_SUCCESS)
goto on_error;
+ /* Initialize exit callback list. */
+ pj_list_init(&endpt->exit_cb_list);
+
/* Create ioqueue if none is specified. */
if (endpt->ioqueue == NULL) {
@@ -188,6 +203,7 @@ PJ_DEF(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt)
*/
PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
{
+ exit_cb *ecb;
unsigned i;
PJ_ASSERT_RETURN(endpt, PJ_EINVAL);
@@ -203,6 +219,13 @@ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt)
}
}
+ /* Call all registered exit callbacks */
+ ecb = endpt->exit_cb_list.next;
+ while (ecb != &endpt->exit_cb_list) {
+ (*ecb->func)(endpt);
+ ecb = ecb->next;
+ }
+
/* Destroy internal ioqueue */
if (endpt->ioqueue && endpt->own_ioqueue) {
pj_ioqueue_destroy(endpt->ioqueue);
@@ -628,3 +651,23 @@ PJ_DEF(pj_status_t) pjmedia_endpt_dump(pjmedia_endpt *endpt)
return PJ_SUCCESS;
}
+
+PJ_DEF(pj_status_t) pjmedia_endpt_atexit( pjmedia_endpt *endpt,
+ pjmedia_endpt_exit_callback func)
+{
+ exit_cb *new_cb;
+
+ PJ_ASSERT_RETURN(endpt && func, PJ_EINVAL);
+
+ if (endpt->quit_flag)
+ return PJ_EINVALIDOP;
+
+ new_cb = PJ_POOL_ZALLOC_T(endpt->pool, exit_cb);
+ new_cb->func = func;
+
+ pj_enter_critical_section();
+ pj_list_push_back(&endpt->exit_cb_list, new_cb);
+ pj_leave_critical_section();
+
+ return PJ_SUCCESS;
+}
diff --git a/pjmedia/src/pjmedia/transport_srtp.c b/pjmedia/src/pjmedia/transport_srtp.c
index b37fd79b..76bd1518 100644
--- a/pjmedia/src/pjmedia/transport_srtp.c
+++ b/pjmedia/src/pjmedia/transport_srtp.c
@@ -270,9 +270,9 @@ const char* get_libsrtp_errstr(int err)
}
static pj_bool_t libsrtp_initialized;
-static void pjmedia_srtp_deinit_lib(void);
+static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt);
-PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
+PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(pjmedia_endpt *endpt)
{
if (libsrtp_initialized == PJ_FALSE) {
err_status_t err;
@@ -284,7 +284,8 @@ PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
return PJMEDIA_ERRNO_FROM_LIBSRTP(err);
}
- if (pj_atexit(pjmedia_srtp_deinit_lib) != PJ_SUCCESS) {
+ if (pjmedia_endpt_atexit(endpt, pjmedia_srtp_deinit_lib) != PJ_SUCCESS)
+ {
/* There will be memory leak when it fails to schedule libsrtp
* deinitialization, however the memory leak could be harmless,
* since in modern OS's memory used by an application is released
@@ -299,10 +300,19 @@ PJ_DEF(pj_status_t) pjmedia_srtp_init_lib(void)
return PJ_SUCCESS;
}
-static void pjmedia_srtp_deinit_lib(void)
+static void pjmedia_srtp_deinit_lib(pjmedia_endpt *endpt)
{
err_status_t err;
+ /* Note that currently this SRTP init/deinit is not equipped with
+ * reference counter, it should be safe as normally there is only
+ * one single instance of media endpoint and even if it isn't, the
+ * pjmedia_transport_srtp_create() will invoke SRTP init (the only
+ * drawback should be the delay described by #788).
+ */
+
+ PJ_UNUSED_ARG(endpt);
+
err = srtp_deinit();
if (err != err_status_ok) {
PJ_LOG(4, (THIS_FILE, "Failed to deinitialize libsrtp: %s",
@@ -410,7 +420,7 @@ PJ_DEF(pj_status_t) pjmedia_transport_srtp_create(
}
/* Init libsrtp. */
- status = pjmedia_srtp_init_lib();
+ status = pjmedia_srtp_init_lib(endpt);
if (status != PJ_SUCCESS)
return status;
diff --git a/pjsip/include/pjsip/sip_endpoint.h b/pjsip/include/pjsip/sip_endpoint.h
index e957271c..bc652e60 100644
--- a/pjsip/include/pjsip/sip_endpoint.h
+++ b/pjsip/include/pjsip/sip_endpoint.h
@@ -62,6 +62,13 @@ PJ_BEGIN_DECL
* @{
*/
+
+/**
+ * Type of callback to register to pjsip_endpt_atexit().
+ */
+typedef void (*pjsip_endpt_exit_callback)(pjsip_endpoint *endpt);
+
+
/**
* Create an instance of SIP endpoint from the specified pool factory.
* The pool factory reference then will be kept by the endpoint, so that
@@ -511,6 +518,18 @@ PJ_DECL(const pjsip_hdr*) pjsip_endpt_get_request_headers(pjsip_endpoint *e);
PJ_DECL(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail );
+/**
+ * Register cleanup function to be called by SIP endpoint when
+ * #pjsip_endpt_destroy() is called.
+ *
+ * @param endpt The SIP endpoint.
+ * @param func The function to be registered.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjsip_endpt_atexit(pjsip_endpoint *endpt,
+ pjsip_endpt_exit_callback func);
+
/**
* @}
diff --git a/pjsip/src/pjsip-ua/sip_replaces.c b/pjsip/src/pjsip-ua/sip_replaces.c
index 4707a510..70329f97 100644
--- a/pjsip/src/pjsip-ua/sip_replaces.c
+++ b/pjsip/src/pjsip-ua/sip_replaces.c
@@ -162,8 +162,10 @@ static pjsip_hdr *parse_hdr_replaces(pjsip_parse_ctx *ctx)
/* Deinitialize Replaces */
-static void pjsip_replaces_deinit_module(void)
+static void pjsip_replaces_deinit_module(pjsip_endpoint *endpt)
{
+ PJ_TODO(provide_initialized_flag_for_each_endpoint);
+ PJ_UNUSED_ARG(endpt);
is_initialized = PJ_FALSE;
}
@@ -191,7 +193,8 @@ PJ_DEF(pj_status_t) pjsip_replaces_init_module(pjsip_endpoint *endpt)
1, &STR_REPLACES);
/* Register deinit module to be executed when PJLIB shutdown */
- if (pj_atexit(&pjsip_replaces_deinit_module) != PJ_SUCCESS) {
+ if (pjsip_endpt_atexit(endpt, &pjsip_replaces_deinit_module) != PJ_SUCCESS)
+ {
/* Failure to register this function may cause this module won't
* work properly when the stack is restarted (without quitting
* application).
diff --git a/pjsip/src/pjsip-ua/sip_timer.c b/pjsip/src/pjsip-ua/sip_timer.c
index d907794f..17c83c24 100644
--- a/pjsip/src/pjsip-ua/sip_timer.c
+++ b/pjsip/src/pjsip-ua/sip_timer.c
@@ -495,8 +495,10 @@ static void stop_timer(pjsip_inv_session *inv)
}
/* Deinitialize Session Timers */
-static void pjsip_timer_deinit_module(void)
+static void pjsip_timer_deinit_module(pjsip_endpoint *endpt)
{
+ PJ_TODO(provide_initialized_flag_for_each_endpoint);
+ PJ_UNUSED_ARG(endpt);
is_initialized = PJ_FALSE;
}
@@ -531,7 +533,7 @@ PJ_DEF(pj_status_t) pjsip_timer_init_module(pjsip_endpoint *endpt)
return status;
/* Register deinit module to be executed when PJLIB shutdown */
- if (pj_atexit(&pjsip_timer_deinit_module) != PJ_SUCCESS) {
+ if (pjsip_endpt_atexit(endpt, &pjsip_timer_deinit_module) != PJ_SUCCESS) {
/* Failure to register this function may cause this module won't
* work properly when the stack is restarted (without quitting
* application).
diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
index 6d3bcdd2..0125ae39 100644
--- a/pjsip/src/pjsip/sip_endpoint.c
+++ b/pjsip/src/pjsip/sip_endpoint.c
@@ -40,6 +40,15 @@
#define MAX_METHODS 32
+
+/* List of SIP endpoint exit callback. */
+typedef struct exit_cb
+{
+ PJ_DECL_LIST_MEMBER (struct exit_cb);
+ pjsip_endpt_exit_callback func;
+} exit_cb;
+
+
/**
* The SIP endpoint.
*/
@@ -86,6 +95,9 @@ struct pjsip_endpoint
/** Additional request headers. */
pjsip_hdr req_hdr;
+
+ /** List of exit callback. */
+ exit_cb exit_cb_list;
};
@@ -445,6 +457,9 @@ PJ_DEF(pj_status_t) pjsip_endpt_create(pj_pool_factory *pf,
/* Init modules list. */
pj_list_init(&endpt->module_list);
+ /* Initialize exit callback list. */
+ pj_list_init(&endpt->exit_cb_list);
+
/* Create R/W mutex for module manipulation. */
status = pj_rwmutex_create(endpt->pool, "ept%p", &endpt->mod_mutex);
if (status != PJ_SUCCESS)
@@ -559,9 +574,17 @@ on_error:
PJ_DEF(void) pjsip_endpt_destroy(pjsip_endpoint *endpt)
{
pjsip_module *mod;
+ exit_cb *ecb;
PJ_LOG(5, (THIS_FILE, "Destroying endpoing instance.."));
+ /* Call all registered exit callbacks */
+ ecb = endpt->exit_cb_list.next;
+ while (ecb != &endpt->exit_cb_list) {
+ (*ecb->func)(endpt);
+ ecb = ecb->next;
+ }
+
/* Phase 1: stop all modules */
mod = endpt->module_list.prev;
while (mod != &endpt->module_list) {
@@ -1178,3 +1201,20 @@ PJ_DEF(void) pjsip_endpt_dump( pjsip_endpoint *endpt, pj_bool_t detail )
#endif
}
+
+PJ_DEF(pj_status_t) pjsip_endpt_atexit( pjsip_endpoint *endpt,
+ pjsip_endpt_exit_callback func)
+{
+ exit_cb *new_cb;
+
+ PJ_ASSERT_RETURN(endpt && func, PJ_EINVAL);
+
+ new_cb = PJ_POOL_ZALLOC_T(endpt->pool, exit_cb);
+ new_cb->func = func;
+
+ pj_mutex_lock(endpt->mutex);
+ pj_list_push_back(&endpt->exit_cb_list, new_cb);
+ pj_mutex_unlock(endpt->mutex);
+
+ return PJ_SUCCESS;
+}
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index d36c9fc2..2a9927a7 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -335,8 +335,8 @@ pj_status_t pjsua_media_subsys_init(const pjsua_media_config *cfg)
PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);
#if defined(PJMEDIA_HAS_SRTP) && (PJMEDIA_HAS_SRTP != 0)
- /* Initialize SRTP library. */
- status = pjmedia_srtp_init_lib();
+ /* Initialize SRTP library (ticket #788). */
+ status = pjmedia_srtp_init_lib(pjsua_var.med_endpt);
if (status != PJ_SUCCESS) {
pjsua_perror(THIS_FILE, "Error initializing SRTP library",
status);