Ticket #970: More gracefull PJSUA-LIB shutdown sequence. Enhancements:
- wait for unregistration to complete (or a preconfigured delay expires)
- new account config field to set the maximum delay to wait for unregistration
- rejects incoming requests (INVITE, SUBSCRIBE, and OPTIONS) when shutdown is in progress
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@2943 74dad513-b988-da41-8d7b-12977e46ad98
diff --git a/pjsip/src/pjsua-lib/pjsua_call.c b/pjsip/src/pjsua-lib/pjsua_call.c
index c57873f..a845940 100644
--- a/pjsip/src/pjsua-lib/pjsua_call.c
+++ b/pjsip/src/pjsua-lib/pjsua_call.c
@@ -645,6 +645,14 @@
if (dlg || tsx)
return PJ_FALSE;
+ /* Don't want to accept the call if shutdown is in progress */
+ if (pjsua_var.thread_quit_flag) {
+ pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
+ PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
PJSUA_LOCK();
/* Find free call slot. */
diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c
index 39ad80d..0b6f48c 100644
--- a/pjsip/src/pjsua-lib/pjsua_core.c
+++ b/pjsip/src/pjsua-lib/pjsua_core.c
@@ -161,6 +161,7 @@
pj_bzero(cfg, sizeof(*cfg));
cfg->reg_timeout = PJSUA_REG_INTERVAL;
+ cfg->unreg_timeout = PJSUA_UNREG_TIMEOUT;
pjsip_publishc_opt_default(&cfg->publish_opt);
cfg->unpublish_max_wait_time_msec = PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC;
cfg->transport_id = PJSUA_INVALID_ID;
@@ -305,6 +306,14 @@
return PJ_FALSE;
}
+ /* Don't want to handle if shutdown is in progress */
+ if (pjsua_var.thread_quit_flag) {
+ pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
+ PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
/* Create basic response. */
status = pjsip_endpt_create_response(pjsua_var.endpt, rdata, 200, NULL,
&tdata);
@@ -1231,6 +1240,8 @@
if (pjsua_var.endpt) {
unsigned max_wait;
+ PJ_LOG(4,(THIS_FILE, "Shutting down..."));
+
/* Terminate all calls. */
pjsua_call_hangup_all();
@@ -1245,6 +1256,9 @@
/* Terminate all presence subscriptions. */
pjsua_pres_shutdown();
+ /* Destroy media (to shutdown media transports etc) */
+ pjsua_media_subsys_destroy();
+
/* Wait for sometime until all publish client sessions are done
* (ticket #364)
*/
@@ -1290,10 +1304,6 @@
pjsua_acc_set_registration(i, PJ_FALSE);
}
}
- }
-
- /* Destroy endpoint. */
- if (pjsua_var.endpt) {
/* Terminate any pending STUN resolution */
if (!pj_list_empty(&pjsua_var.stun_res)) {
@@ -1305,24 +1315,41 @@
}
}
+ /* Wait until all unregistrations are done (ticket #364) */
+ /* First stage, get the maximum wait time */
+ max_wait = 100;
+ for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
+ if (!pjsua_var.acc[i].valid)
+ continue;
+ if (pjsua_var.acc[i].cfg.unreg_timeout > max_wait)
+ max_wait = pjsua_var.acc[i].cfg.unreg_timeout;
+ }
+
+ /* Second stage, wait for unregistrations to complete */
+ for (i=0; i<(int)(max_wait/50); ++i) {
+ unsigned j;
+ for (j=0; j<PJ_ARRAY_SIZE(pjsua_var.acc); ++j) {
+ if (!pjsua_var.acc[j].valid)
+ continue;
+
+ if (pjsua_var.acc[j].regc)
+ break;
+ }
+ if (j != PJ_ARRAY_SIZE(pjsua_var.acc))
+ busy_sleep(50);
+ else
+ break;
+ }
+ /* Note variable 'i' is used below */
+
/* Wait for some time to allow unregistration and ICE/TURN
* transports shutdown to complete:
- */
- PJ_LOG(4,(THIS_FILE, "Shutting down..."));
- busy_sleep(1000);
+ */
+ if (i < 20)
+ busy_sleep(1000 - i*50);
PJ_LOG(4,(THIS_FILE, "Destroying..."));
- /* Terminate all calls again, just in case there's new call
- * picked up during busy_sleep()
- */
- pjsua_call_hangup_all();
-
- /* Destroy media after all polling is done, as there may be
- * incoming request that needs handling (e.g. OPTIONS)
- */
- pjsua_media_subsys_destroy();
-
/* Must destroy endpoint first before destroying pools in
* buddies or accounts, since shutting down transaction layer
* may emit events which trigger some buddy or account callbacks
@@ -1346,9 +1373,6 @@
pjsua_var.acc[i].pool = NULL;
}
}
- } else {
- /* Destroy media */
- pjsua_media_subsys_destroy();
}
/* Destroy mutex */
diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c
index 243f4f6..01f33a1 100644
--- a/pjsip/src/pjsua-lib/pjsua_media.c
+++ b/pjsip/src/pjsua-lib/pjsua_media.c
@@ -640,6 +640,8 @@
{
unsigned i;
+ PJ_LOG(4,(THIS_FILE, "Shutting down media.."));
+
close_snd_dev();
if (pjsua_var.mconf) {
diff --git a/pjsip/src/pjsua-lib/pjsua_pres.c b/pjsip/src/pjsua-lib/pjsua_pres.c
index 4515636..935a41e 100644
--- a/pjsip/src/pjsua-lib/pjsua_pres.c
+++ b/pjsip/src/pjsua-lib/pjsua_pres.c
@@ -682,6 +682,14 @@
/* Incoming SUBSCRIBE: */
+ /* Don't want to accept the request if shutdown is in progress */
+ if (pjsua_var.thread_quit_flag) {
+ pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata,
+ PJSIP_SC_TEMPORARILY_UNAVAILABLE, NULL,
+ NULL, NULL);
+ return PJ_TRUE;
+ }
+
PJSUA_LOCK();
/* Find which account for the incoming request. */
@@ -1721,6 +1729,8 @@
{
unsigned i;
+ PJ_LOG(4,(THIS_FILE, "Shutting down presence.."));
+
if (pjsua_var.pres_timer.id != 0) {
pjsip_endpt_cancel_timer(pjsua_var.endpt, &pjsua_var.pres_timer);
pjsua_var.pres_timer.id = PJ_FALSE;