From 1321a047fb6d74374f7948eda41ad5c84884daab Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Thu, 19 Jun 2014 09:42:02 +0000 Subject: Fix #1773: Added group lock to SIP transport to avoid race condition between transport callback and destroy. git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4862 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/include/pj/ssl_sock.h | 16 ++++++++++++++++ pjlib/src/pj/ssl_sock_ossl.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) (limited to 'pjlib') diff --git a/pjlib/include/pj/ssl_sock.h b/pjlib/include/pj/ssl_sock.h index 23843717..92e86aab 100644 --- a/pjlib/include/pj/ssl_sock.h +++ b/pjlib/include/pj/ssl_sock.h @@ -552,6 +552,11 @@ typedef struct pj_ssl_sock_info */ unsigned long last_native_err; + /** + * Group lock assigned to the ioqueue key. + */ + pj_grp_lock_t *grp_lock; + } pj_ssl_sock_info; @@ -560,6 +565,17 @@ typedef struct pj_ssl_sock_info */ typedef struct pj_ssl_sock_param { + /** + * Optional group lock to be assigned to the ioqueue key. + * + * Note that when a secure socket listener is configured with a group + * lock, any new secure socket of an accepted incoming connection + * will have its own group lock created automatically by the library, + * this group lock can be queried via pj_ssl_sock_get_info() in the info + * field pj_ssl_sock_info::grp_lock. + */ + pj_grp_lock_t *grp_lock; + /** * Specifies socket address family, either pj_AF_INET() and pj_AF_INET6(). * diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c index 3aa85b0d..cc99433d 100644 --- a/pjlib/src/pj/ssl_sock_ossl.c +++ b/pjlib/src/pj/ssl_sock_ossl.c @@ -1693,6 +1693,24 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, asock_cfg.async_cnt = ssock->param.async_cnt; asock_cfg.concurrency = ssock->param.concurrency; asock_cfg.whole_data = PJ_TRUE; + + /* If listener socket has group lock, automatically create group lock + * for the new socket. + */ + if (ssock_parent->param.grp_lock) { + pj_grp_lock_t *glock; + + status = pj_grp_lock_create(ssock->pool, NULL, &glock); + if (status != PJ_SUCCESS) + goto on_return; + + /* Temporarily add ref the group lock until active socket creation, + * to make sure that group lock is destroyed if the active socket + * creation fails. + */ + pj_grp_lock_add_ref(glock); + asock_cfg.grp_lock = ssock->param.grp_lock = glock; + } pj_bzero(&asock_cb, sizeof(asock_cb)); asock_cb.on_data_read = asock_on_data_read; @@ -1707,6 +1725,11 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock, ssock, &ssock->asock); + /* This will destroy the group lock if active socket creation fails */ + if (asock_cfg.grp_lock) { + pj_grp_lock_dec_ref(asock_cfg.grp_lock); + } + if (status != PJ_SUCCESS) goto on_return; @@ -2122,6 +2145,9 @@ PJ_DEF(pj_status_t) pj_ssl_sock_get_info (pj_ssl_sock_t *ssock, /* Last known OpenSSL error code */ info->last_native_err = ssock->last_err; + /* Group lock */ + info->grp_lock = ssock->param.grp_lock; + return PJ_SUCCESS; } @@ -2488,6 +2514,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_accept (pj_ssl_sock_t *ssock, asock_cfg.async_cnt = ssock->param.async_cnt; asock_cfg.concurrency = ssock->param.concurrency; asock_cfg.whole_data = PJ_TRUE; + asock_cfg.grp_lock = ssock->param.grp_lock; pj_bzero(&asock_cb, sizeof(asock_cb)); asock_cb.on_accept_complete = asock_on_accept_complete; @@ -2574,6 +2601,7 @@ PJ_DECL(pj_status_t) pj_ssl_sock_start_connect(pj_ssl_sock_t *ssock, asock_cfg.async_cnt = ssock->param.async_cnt; asock_cfg.concurrency = ssock->param.concurrency; asock_cfg.whole_data = PJ_TRUE; + asock_cfg.grp_lock = ssock->param.grp_lock; pj_bzero(&asock_cb, sizeof(asock_cb)); asock_cb.on_connect_complete = asock_on_connect_complete; -- cgit v1.2.3