Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 2941)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 2942)
@@ -1752,4 +1752,20 @@
 
 /**
+ * Maximum time to wait for unpublication transaction(s) to complete
+ * during shutdown process, before sending unregistration. The library
+ * tries to wait for the unpublication (un-PUBLISH) to complete before
+ * sending REGISTER request to unregister the account, during library
+ * shutdown process. If the value is set too short, it is possible that
+ * the unregistration is sent before unpublication completes, causing
+ * unpublication request to fail.
+ *
+ * Default: 2000 (2 seconds)
+ */
+#ifndef PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC
+#   define PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC	2000
+#endif
+
+
+/**
  * This structure describes account configuration to be specified when
  * adding a new account with #pjsua_acc_add(). Application MUST initialize
@@ -1801,4 +1817,17 @@
      */
     pjsip_publishc_opt	publish_opt;
+
+    /**
+     * Maximum time to wait for unpublication transaction(s) to complete
+     * during shutdown process, before sending unregistration. The library
+     * tries to wait for the unpublication (un-PUBLISH) to complete before
+     * sending REGISTER request to unregister the account, during library
+     * shutdown process. If the value is set too short, it is possible that
+     * the unregistration is sent before unpublication completes, causing
+     * unpublication request to fail.
+     *
+     * Default: PJSUA_UNPUBLISH_MAX_WAIT_TIME_MSEC
+     */
+    unsigned	    unpublish_max_wait_time_msec;
 
     /**
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2941)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 2942)
@@ -163,4 +163,5 @@
     cfg->reg_timeout = PJSUA_REG_INTERVAL;
     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;
     cfg->allow_contact_rewrite = PJ_TRUE;
@@ -1229,4 +1230,6 @@
     
     if (pjsua_var.endpt) {
+	unsigned max_wait;
+
 	/* Terminate all calls. */
 	pjsua_call_hangup_all();
@@ -1242,4 +1245,40 @@
 	/* Terminate all presence subscriptions. */
 	pjsua_pres_shutdown();
+
+	/* Wait for sometime until all publish client sessions 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.unpublish_max_wait_time_msec > max_wait)
+		max_wait = pjsua_var.acc[i].cfg.unpublish_max_wait_time_msec;
+	}
+	
+	/* Second stage, wait for unpublications 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].publish_sess)
+		    break;
+	    }
+	    if (j != PJ_ARRAY_SIZE(pjsua_var.acc))
+		busy_sleep(50);
+	    else
+		break;
+	}
+
+	/* Third stage, forcefully destroy unfinished unpublications */
+	for (i=0; i<PJ_ARRAY_SIZE(pjsua_var.acc); ++i) {
+	    if (pjsua_var.acc[i].publish_sess) {
+		pjsip_publishc_destroy(pjsua_var.acc[i].publish_sess);
+		pjsua_var.acc[i].publish_sess = NULL;
+	    }
+	}
 
 	/* Unregister all accounts */
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 2941)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 2942)
@@ -993,5 +993,5 @@
 
     } else {
-	if (param->expiration == -1) {
+	if (param->expiration < 1) {
 	    /* Could happen if server "forgot" to include Expires header
 	     * in the response. We will not renew, so destroy the pubc.
@@ -1202,8 +1202,11 @@
 	acc->online_status = PJ_FALSE;
 	send_publish(acc_id, PJ_FALSE);
+	/* By ticket #364, don't destroy the session yet (let the callback
+	   destroy it)
 	if (acc->publish_sess) {
 	    pjsip_publishc_destroy(acc->publish_sess);
 	    acc->publish_sess = NULL;
 	}
+	*/
 	acc_cfg->publish_enabled = PJ_FALSE;
     }
