Index: pjproject/trunk/pjsip-apps/src/samples/footprint.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/footprint.c	(revision 5240)
+++ pjproject/trunk/pjsip-apps/src/samples/footprint.c	(revision 5241)
@@ -342,5 +342,5 @@
     pjsip_ua_destroy();
     pjsip_dlg_create_uac(NULL, NULL, NULL, NULL, NULL, NULL);
-    pjsip_dlg_create_uas(NULL, NULL, NULL, NULL);
+    pjsip_dlg_create_uas_and_inc_lock(NULL, NULL, NULL, NULL);
     pjsip_dlg_terminate(NULL);
     pjsip_dlg_set_route_set(NULL, NULL);
Index: pjproject/trunk/pjsip-apps/src/samples/pjsip-perf.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/pjsip-perf.c	(revision 5240)
+++ pjproject/trunk/pjsip-apps/src/samples/pjsip-perf.c	(revision 5241)
@@ -476,6 +476,6 @@
 
     /* Create UAS dialog */
-    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
-				   &app.local_contact, &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(), rdata,
+						&app.local_contact, &dlg);
     if (status != PJ_SUCCESS) {
 	const pj_str_t reason = pj_str("Unable to create dialog");
@@ -503,7 +503,11 @@
 	pjsip_dlg_create_response(dlg, rdata, 500, NULL, &tdata);
 	pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
+	pjsip_dlg_dec_lock(dlg);
 	return PJ_TRUE;
     }
     
+    /* Invite session has been created, decrement & release dialog lock. */
+    pjsip_dlg_dec_lock(dlg);
+
     /* Send 100/Trying if needed */
     if (app.server.send_trying) {
Index: pjproject/trunk/pjsip-apps/src/samples/simpleua.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/simpleua.c	(revision 5240)
+++ pjproject/trunk/pjsip-apps/src/samples/simpleua.c	(revision 5241)
@@ -726,8 +726,8 @@
      * Create UAS dialog.
      */
-    status = pjsip_dlg_create_uas( pjsip_ua_instance(), 
-				   rdata,
-				   &local_uri, /* contact */
-				   &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(),
+						rdata,
+						&local_uri, /* contact */
+						&dlg);
     if (status != PJ_SUCCESS) {
 	pjsip_endpt_respond_stateless(g_endpt, rdata, 500, NULL,
@@ -742,5 +742,9 @@
     status = pjmedia_endpt_create_sdp( g_med_endpt, rdata->tp_info.pool,
 				       MAX_MEDIA_CNT, g_sock_info, &local_sdp);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+    pj_assert(status == PJ_SUCCESS);
+    if (status != PJ_SUCCESS) {
+	pjsip_dlg_dec_lock(dlg);
+	return PJ_TRUE;
+    }
 
 
@@ -750,5 +754,14 @@
      */
     status = pjsip_inv_create_uas( dlg, rdata, local_sdp, 0, &g_inv);
-    PJ_ASSERT_RETURN(status == PJ_SUCCESS, PJ_TRUE);
+    pj_assert(status == PJ_SUCCESS);
+    if (status != PJ_SUCCESS) {
+	pjsip_dlg_dec_lock(dlg);
+	return PJ_TRUE;
+    }
+
+    /*
+     * Invite session has been created, decrement & release dialog lock.
+     */
+    pjsip_dlg_dec_lock(dlg);
 
 
Index: pjproject/trunk/pjsip-apps/src/samples/sipecho.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/sipecho.c	(revision 5240)
+++ pjproject/trunk/pjsip-apps/src/samples/sipecho.c	(revision 5241)
@@ -418,5 +418,5 @@
     char temp[80], hostip[PJ_INET6_ADDRSTRLEN];
     pj_str_t local_uri;
-    pjsip_dialog *dlg;
+    pjsip_dialog *dlg = NULL;
     pjsip_rdata_sdp_info *sdp_info;
     pjmedia_sdp_session *answer = NULL;
@@ -499,11 +499,16 @@
     local_uri = pj_str(temp);
 
-    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
-				   &local_uri, &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(), rdata,
+						&local_uri, &dlg);
 
     if (status == PJ_SUCCESS)
 	answer = create_answer((int)(call-app.call), dlg->pool, sdp_info->sdp);
+
     if (status == PJ_SUCCESS)
     	status = pjsip_inv_create_uas( dlg, rdata, answer, 0, &call->inv);
+
+    if (dlg)
+	pjsip_dlg_dec_lock(dlg);
+
     if (status == PJ_SUCCESS)
     	status = pjsip_inv_initial_answer(call->inv, rdata, 100,
Index: pjproject/trunk/pjsip-apps/src/samples/siprtp.c
===================================================================
--- pjproject/trunk/pjsip-apps/src/samples/siprtp.c	(revision 5240)
+++ pjproject/trunk/pjsip-apps/src/samples/siprtp.c	(revision 5241)
@@ -638,6 +638,6 @@
 
     /* Create UAS dialog */
-    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
-				   &app.local_contact, &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(), rdata,
+						&app.local_contact, &dlg);
     if (status != PJ_SUCCESS) {
 	const pj_str_t reason = pj_str("Unable to create dialog");
@@ -656,7 +656,10 @@
 	pjsip_dlg_create_response(dlg, rdata, 500, NULL, &tdata);
 	pjsip_dlg_send_response(dlg, pjsip_rdata_get_tsx(rdata), tdata);
+	pjsip_dlg_dec_lock(dlg);
 	return;
     }
     
+    /* Invite session has been created, decrement & release dialog lock */
+    pjsip_dlg_dec_lock(dlg);
 
     /* Attach call data to invite session */
Index: pjproject/trunk/pjsip/include/pjsip-ua/sip_replaces.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip-ua/sip_replaces.h	(revision 5240)
+++ pjproject/trunk/pjsip/include/pjsip-ua/sip_replaces.h	(revision 5241)
@@ -139,5 +139,5 @@
     // Create UAS Invite session as usual.
     //
-    status = pjsip_dlg_create_uas(.., rdata, .., &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock(.., rdata, .., &dlg);
     ..
     status = pjsip_inv_create_uas(dlg, .., &inv);
Index: pjproject/trunk/pjsip/include/pjsip/sip_dialog.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsip/sip_dialog.h	(revision 5240)
+++ pjproject/trunk/pjsip/include/pjsip/sip_dialog.h	(revision 5241)
@@ -61,4 +61,13 @@
 PJ_BEGIN_DECL
 
+
+/* Deprecated API pjsip_dlg_create_uas() due to a fatal bug of possible
+ * premature dialog destroy. Application should not change this setting,
+ * unless it uses single worker thread.
+ * See also https://trac.pjsip.org/repos/ticket/1902.
+ */
+#ifndef DEPRECATED_FOR_TICKET_1902
+#  define DEPRECATED_FOR_TICKET_1902      1
+#endif
 
 /**
@@ -241,4 +250,5 @@
 
 
+#if !DEPRECATED_FOR_TICKET_1902
 /**
  * Initialize UAS dialog from the information found in the incoming request 
@@ -280,4 +290,48 @@
 					    const pj_str_t *contact,
 					    pjsip_dialog **p_dlg);
+#endif
+
+
+/**
+ * Initialize UAS dialog from the information found in the incoming request 
+ * that creates a dialog (such as INVITE, REFER, or SUBSCRIBE), and set the 
+ * local Contact to contact. If contact is not specified, the local contact 
+ * is initialized from the URI in the To header in the request. 
+ *
+ * This function will also create UAS transaction for the incoming request,
+ * and associate the transaction to the rdata. Application can query the
+ * transaction used to handle this request by calling #pjsip_rdata_get_tsx()
+ * after this function returns.
+ *
+ * Note that initially, the session count in the dialog will be initialized 
+ * to 1 (one), and the dialog is locked. Application needs to explicitly call
+ * #pjsip_dlg_dec_lock() to release the lock and decrease the session count.
+ *
+ *
+ * @param ua		    The user agent module instance.
+ * @param rdata		    The incoming request that creates the dialog,
+ *			    such as INVITE, SUBSCRIBE, or REFER.
+ * @param contact	    Optional dialog local Contact to be put as Contact
+ *			    header value, hence the format must follow
+ *			    RFC 3261 Section 20.10:
+ *			    When the header field value contains a display 
+ *			    name, the URI including all URI parameters is 
+ *			    enclosed in "<" and ">".  If no "<" and ">" are 
+ *			    present, all parameters after the URI are header
+ *			    parameters, not URI parameters.  The display name 
+ *			    can be tokens, or a quoted string, if a larger 
+ *			    character set is desired.
+ *			    If this argument is NULL, the local contact will be
+ *			    initialized from the value of To header in the
+ *			    request.
+ * @param p_dlg		    Pointer to receive the dialog.
+ *
+ * @return		    PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t)
+pjsip_dlg_create_uas_and_inc_lock(    pjsip_user_agent *ua,
+				      pjsip_rx_data *rdata,
+				      const pj_str_t *contact,
+				      pjsip_dialog **p_dlg);
 
 
@@ -362,6 +416,7 @@
  * established, the route set can not be changed.
  *
- * For UAS dialog,the route set will be initialized in pjsip_dlg_create_uas()
- * from the Record-Route headers in the incoming request.
+ * For UAS dialog, the route set will be initialized in
+ * pjsip_dlg_create_uas_and_inc_lock() from the Record-Route headers in
+ * the incoming request.
  *
  * The route_set argument is standard list of Route headers (i.e. with 
Index: pjproject/trunk/pjsip/src/pjsip/sip_dialog.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/pjsip/sip_dialog.c	(revision 5241)
@@ -312,8 +312,9 @@
  * Create UAS dialog.
  */
-PJ_DEF(pj_status_t) pjsip_dlg_create_uas(   pjsip_user_agent *ua,
-					    pjsip_rx_data *rdata,
-					    const pj_str_t *contact,
-					    pjsip_dialog **p_dlg)
+pj_status_t create_uas_dialog( pjsip_user_agent *ua,
+			       pjsip_rx_data *rdata,
+			       const pj_str_t *contact,
+			       pj_bool_t inc_lock,
+			       pjsip_dialog **p_dlg)
 {
     pj_status_t status;
@@ -511,4 +512,10 @@
 	goto on_error;
 
+    /* Increment the dialog's lock since tsx may cause the dialog to be
+     * destroyed prematurely (such as in case of transport error).
+     */
+    if (inc_lock)
+        pjsip_dlg_inc_lock(dlg);
+
     /* Create UAS transaction for this request. */
     status = pjsip_tsx_create_uas(dlg->ua, rdata, &tsx);
@@ -553,6 +560,38 @@
     }
 
-    destroy_dialog(dlg, PJ_FALSE);
+    if (inc_lock) {
+        pjsip_dlg_dec_lock(dlg);
+    } else {
+        destroy_dialog(dlg, PJ_FALSE);
+    }
+    
     return status;
+}
+
+
+#if !DEPRECATED_FOR_TICKET_1902
+/*
+ * Create UAS dialog.
+ */
+PJ_DEF(pj_status_t) pjsip_dlg_create_uas(   pjsip_user_agent *ua,
+					    pjsip_rx_data *rdata,
+					    const pj_str_t *contact,
+					    pjsip_dialog **p_dlg)
+{
+    return create_uas_dialog(ua, rdata, contact, PJ_FALSE, p_dlg);
+}
+#endif
+
+
+/*
+ * Create UAS dialog and increase its session count.
+ */
+PJ_DEF(pj_status_t)
+pjsip_dlg_create_uas_and_inc_lock(    pjsip_user_agent *ua,
+				      pjsip_rx_data *rdata,
+				      const pj_str_t *contact,
+				      pjsip_dialog **p_dlg)
+{
+    return create_uas_dialog(ua, rdata, contact, PJ_TRUE, p_dlg);
 }
 
Index: pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 5241)
@@ -139,4 +139,10 @@
 #define TRANSPORT_ERR_TIMER	3
 
+/* Flags for tsx_set_state() */
+enum
+{
+    NO_NOTIFY = 1,
+    NO_SCHEDULE_HANDLER = 2,
+};
 
 /* Prototypes. */
@@ -170,9 +176,6 @@
             	                  pjsip_tsx_state_e state,
             	                  pjsip_event_id_e event_src_type,
-            	                  void *event_src );
-static void 	   tsx_set_state_no_notify( pjsip_transaction *tsx,
-            	                            pjsip_tsx_state_e state,
-            	                            pjsip_event_id_e event_src_type,
-            	                            void *event_src );
+            	                  void *event_src,
+				  int flag);
 static void 	   tsx_set_status_code(pjsip_transaction *tsx,
             	                       int code, const pj_str_t *reason);
@@ -1104,4 +1107,5 @@
 	if (tsx->state < PJSIP_TSX_STATE_TERMINATED) {
 	    pjsip_tsx_state_e prev_state;
+	    pj_time_val timeout = { 0, 0 };
 
 	    pj_grp_lock_acquire(tsx->grp_lock);
@@ -1123,6 +1127,13 @@
 	     * https://trac.pjsip.org/repos/ticket/1646
 	     */
-	    tsx_set_state_no_notify( tsx, PJSIP_TSX_STATE_TERMINATED,
-	                             PJSIP_EVENT_TRANSPORT_ERROR, NULL);
+	    /* Also don't schedule tsx handler, otherwise we'll get race
+	     * condition of TU notifications due to delayed TERMINATED
+	     * state TU notification. It happened in multiple worker threads
+	     * environment between TERMINATED & DESTROYED! See:
+	     * https://trac.pjsip.org/repos/ticket/1902
+	     */
+	    tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
+	                   PJSIP_EVENT_TRANSPORT_ERROR, NULL,
+			   NO_NOTIFY | NO_SCHEDULE_HANDLER);
 	    pj_grp_lock_release(tsx->grp_lock);
 
@@ -1139,4 +1150,8 @@
 		(*tsx->tsx_user->on_tsx_state)(tsx, &e);
 	    }
+
+	    /* Now let's schedule the tsx handler */
+	    tsx_schedule_timer(tsx, &tsx->timeout_timer, &timeout,
+			       TIMEOUT_TIMER);
 	}
     } else {
@@ -1168,5 +1183,6 @@
 			   pjsip_tsx_state_e state,
 			   pjsip_event_id_e event_src_type,
-                           void *event_src )
+                           void *event_src,
+			   int flag)
 {
     pjsip_tsx_state_e prev_state = tsx->state;
@@ -1193,5 +1209,7 @@
      * rx event.
      */
-    if (event_src_type==PJSIP_EVENT_RX_MSG && tsx->tsx_user) {
+    if (event_src_type==PJSIP_EVENT_RX_MSG && tsx->tsx_user &&
+	(flag & NO_NOTIFY)==0)
+    {
 	pjsip_rx_data *rdata = (pjsip_rx_data*) event_src;
 
@@ -1207,5 +1225,7 @@
 
     /* Inform TU about state changed. */
-    if (tsx->tsx_user && tsx->tsx_user->on_tsx_state) {
+    if (tsx->tsx_user && tsx->tsx_user->on_tsx_state &&
+	(flag & NO_NOTIFY) == 0)
+    {
 	pjsip_event e;
 	PJSIP_EVENT_INIT_TSX_STATE(e, tsx, event_src_type, event_src,
@@ -1219,5 +1239,5 @@
      */
     if (state == PJSIP_TSX_STATE_TERMINATED) {
-	pj_time_val timeout = {0, 0};
+	pj_time_val timeout = { 0, 0 };
 
 	/* If we're still waiting for a message to be sent.. */
@@ -1237,5 +1257,8 @@
 	lock_timer(tsx);
 	tsx_cancel_timer(tsx, &tsx->timeout_timer);
-	tsx_schedule_timer( tsx, &tsx->timeout_timer, &timeout, TIMEOUT_TIMER);
+	if ((flag & NO_SCHEDULE_HANDLER) == 0) {
+	    tsx_schedule_timer(tsx, &tsx->timeout_timer, &timeout,
+			       TIMEOUT_TIMER);
+	}
 	unlock_timer(tsx);
 
@@ -1250,16 +1273,4 @@
 
     pj_log_pop_indent();
-}
-
-/* Set transaction state without notifying tsx_user */
-static void tsx_set_state_no_notify( pjsip_transaction *tsx,
-                                     pjsip_tsx_state_e state,
-                                     pjsip_event_id_e event_src_type,
-                                     void *event_src )
-{
-    pjsip_module *tsx_user = tsx->tsx_user;
-    tsx->tsx_user = NULL;
-    tsx_set_state(tsx, state, event_src_type, event_src);
-    tsx->tsx_user = tsx_user;
 }
 
@@ -1627,5 +1638,6 @@
     if (tsx->state < PJSIP_TSX_STATE_TERMINATED) {
         tsx_set_status_code(tsx, code, NULL);
-        tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER, NULL);
+        tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, PJSIP_EVENT_USER,
+		       NULL, 0);
     }
     pj_grp_lock_release(tsx->grp_lock);
@@ -1838,5 +1850,5 @@
 	if (tsx->transport_flag & TSX_HAS_PENDING_DESTROY) {
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, 
-			   PJSIP_EVENT_UNKNOWN, NULL );
+			   PJSIP_EVENT_UNKNOWN, NULL, 0 );
 	    pj_grp_lock_release(tsx->grp_lock);
 	    return;
@@ -1913,5 +1925,6 @@
 	    {
 		tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
-			       PJSIP_EVENT_TRANSPORT_ERROR, send_state->tdata);
+			       PJSIP_EVENT_TRANSPORT_ERROR,
+			       send_state->tdata, 0);
 	    } 
 	    /* Don't forget to destroy if we have pending destroy flag
@@ -1921,5 +1934,6 @@
 	    {
 		tsx_set_state( tsx, PJSIP_TSX_STATE_DESTROYED, 
-			       PJSIP_EVENT_TRANSPORT_ERROR, send_state->tdata);
+			       PJSIP_EVENT_TRANSPORT_ERROR,
+			       send_state->tdata, 0);
 	    }
 
@@ -2123,5 +2137,5 @@
 	tsx_set_status_code(tsx, PJSIP_SC_TSX_TRANSPORT_ERROR, &err);
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
-		       PJSIP_EVENT_TRANSPORT_ERROR, NULL );
+		       PJSIP_EVENT_TRANSPORT_ERROR, NULL, 0 );
 
 	return status;
@@ -2355,5 +2369,5 @@
 		    PJSIP_REQUEST_MSG);
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TRYING, PJSIP_EVENT_RX_MSG,
-		       event->body.rx_msg.rdata);
+		       event->body.rx_msg.rdata, 0);
 
     } else {
@@ -2410,5 +2424,5 @@
 	/* Move state. */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_CALLING, 
-                       PJSIP_EVENT_TX_MSG, tdata);
+                       PJSIP_EVENT_TX_MSG, tdata, 0);
     }
 
@@ -2451,5 +2465,5 @@
 	/* Inform TU. */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
-                       PJSIP_EVENT_TIMER, &tsx->timeout_timer);
+                       PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0);
 
 	/* Transaction is destroyed */
@@ -2570,5 +2584,5 @@
 
 	tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, 
-                       PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata);
+                       PJSIP_EVENT_TX_MSG, event->body.tx_msg.tdata, 0);
 
     }
@@ -2651,5 +2665,5 @@
 
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, 
-                           PJSIP_EVENT_TX_MSG, tdata );
+                           PJSIP_EVENT_TX_MSG, tdata, 0 );
 
 	    /* Retransmit provisional response every 1 minute if this is
@@ -2685,5 +2699,5 @@
 		 */
 		tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
-                               PJSIP_EVENT_TX_MSG, tdata );
+                               PJSIP_EVENT_TX_MSG, tdata, 0 );
 
 		/* Transaction is destroyed. */
@@ -2743,5 +2757,5 @@
 		/* Set state to "Completed" */
 		tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, 
-                               PJSIP_EVENT_TX_MSG, tdata );
+                               PJSIP_EVENT_TX_MSG, tdata, 0 );
 	    }
 
@@ -2802,5 +2816,5 @@
 	    /* Inform TU */
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, 
-                           PJSIP_EVENT_TX_MSG, tdata );
+                           PJSIP_EVENT_TX_MSG, tdata, 0 );
 
 	} else {
@@ -2836,5 +2850,5 @@
 
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
-                       PJSIP_EVENT_TIMER, &tsx->timeout_timer);
+                       PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0);
 
 	return PJ_EBUG;
@@ -2901,5 +2915,5 @@
 	/* Inform the message to TU. */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_PROCEEDING, 
-                       PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
+                       PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 );
 
     } else if (PJSIP_IS_STATUS_IN_CLASS(tsx->status_code,200)) {
@@ -2915,5 +2929,5 @@
 	if (tsx->method.id == PJSIP_INVITE_METHOD) {
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
-                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
+                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 );
 	    //return PJSIP_ETSXDESTROYED;
 
@@ -2942,5 +2956,5 @@
 	    /* Move state to Completed, inform TU. */
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, 
-                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
+                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 );
 	}
 
@@ -2950,5 +2964,5 @@
 	/* Inform TU. */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
-		       PJSIP_EVENT_TIMER, &tsx->timeout_timer);
+		       PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0);
 
 
@@ -3041,5 +3055,5 @@
 	/* Inform TU. */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_COMPLETED, 
-		       PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata);
+		       PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0);
 
 	/* Generate and send ACK for INVITE. */
@@ -3152,5 +3166,5 @@
 	    /* Move state to "Confirmed" */
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_CONFIRMED, 
-                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata );
+                           PJSIP_EVENT_RX_MSG, event->body.rx_msg.rdata, 0 );
 	}	
 
@@ -3176,5 +3190,5 @@
 
 		tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
-                               PJSIP_EVENT_TIMER, &tsx->timeout_timer );
+                               PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0 );
 
 		//return PJSIP_ETSXDESTROYED;
@@ -3183,5 +3197,5 @@
 		/* Transaction terminated, it can now be deleted. */
 		tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED, 
-                               PJSIP_EVENT_TIMER, &tsx->timeout_timer );
+                               PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0 );
 		//return PJSIP_ETSXDESTROYED;
 	    }
@@ -3216,5 +3230,5 @@
 	/* Move to Terminated state. */
 	tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
-                       PJSIP_EVENT_TIMER, event->body.timer.entry );
+                       PJSIP_EVENT_TIMER, event->body.timer.entry, 0 );
 
 	/* Transaction has been destroyed. */
@@ -3291,5 +3305,5 @@
 	    /* Move to Terminated state. */
 	    tsx_set_state( tsx, PJSIP_TSX_STATE_TERMINATED,
-			   PJSIP_EVENT_TIMER, &tsx->timeout_timer );
+			   PJSIP_EVENT_TIMER, &tsx->timeout_timer, 0 );
 
 	    /* Transaction has been destroyed. */
@@ -3322,5 +3336,5 @@
     /* Destroy this transaction */
     tsx_set_state(tsx, PJSIP_TSX_STATE_DESTROYED, 
-                  event->type, event->body.user.user1 );
+                  event->type, event->body.user.user1, 0 );
 
     return PJ_SUCCESS;
Index: pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/pjsip/sip_ua_layer.c	(revision 5241)
@@ -278,5 +278,5 @@
 /*
  * Register new dialog. Called by pjsip_dlg_create_uac() and
- * pjsip_dlg_create_uas();
+ * pjsip_dlg_create_uas_and_inc_lock();
  */
 PJ_DEF(pj_status_t) pjsip_ua_register_dlg( pjsip_user_agent *ua,
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_call.c	(revision 5241)
@@ -983,8 +983,17 @@
     pjsip_tx_data *response = NULL;
     unsigned options = 0;
+    pjsip_dialog *dlg = call->async_call.dlg;
     int sip_err_code = (info? info->sip_err_code: 0);
     pj_status_t status = (info? info->status: PJ_SUCCESS);
 
     PJSUA_LOCK();
+    
+    /* Increment the dialog's lock to prevent it to be destroyed prematurely,
+     * such as in case of transport error.
+     */
+    pjsip_dlg_inc_lock(dlg);
+
+    /* Decrement dialog session. */
+    pjsip_dlg_dec_session(dlg, &pjsua_var.mod);    
 
     if (status != PJ_SUCCESS) {
@@ -997,4 +1006,5 @@
         pjsua_media_channel_deinit(call->index);
         call->med_ch_cb = NULL;
+        pjsip_dlg_dec_lock(dlg);
         PJSUA_UNLOCK();
         return PJ_SUCCESS;
@@ -1068,5 +1078,7 @@
 	}
     }
-
+    
+    pjsip_dlg_dec_lock(dlg);
+    
     PJSUA_UNLOCK();
     return status;
@@ -1352,6 +1364,6 @@
 
     /* Create dialog: */
-    status = pjsip_dlg_create_uas( pjsip_ua_instance(), rdata,
-				   &contact, &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock( pjsip_ua_instance(), rdata,
+				   		&contact, &dlg);
     if (status != PJ_SUCCESS) {
 	pjsip_endpt_respond_stateless(pjsua_var.endpt, rdata, 500, NULL,
@@ -1460,4 +1472,6 @@
     call->async_call.dlg = dlg;
     pj_list_init(&call->async_call.call_var.inc_call.answers);
+
+    pjsip_dlg_inc_session(dlg, &pjsua_var.mod);
 
     /* Init media channel, only when there is offer or call replace request.
@@ -1502,4 +1516,6 @@
 	    pjsip_dlg_dec_lock(dlg);
 
+	    pjsip_dlg_dec_session(dlg, &pjsua_var.mod);
+
 	    call->inv = NULL;
 	    call->async_call.dlg = NULL;
@@ -1619,4 +1635,8 @@
     /* This INVITE request has been handled. */
 on_return:
+    if (dlg) {
+        pjsip_dlg_dec_lock(dlg);
+    }
+    
     pj_log_pop_indent();
     PJSUA_UNLOCK();
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 5241)
@@ -1106,5 +1106,7 @@
 
 	for (ii=0; ii<pjsua_var.ua_cfg.thread_cnt; ++ii) {
-	    status = pj_thread_create(pjsua_var.pool, "pjsua", &worker_thread,
+	    char thread_name[16];
+	    pj_ansi_snprintf(thread_name, 16, "pjsua_%d", ii);
+	    status = pj_thread_create(pjsua_var.pool, thread_name, &worker_thread,
 				      NULL, 0, 0, &pjsua_var.thread[ii]);
 	    if (status != PJ_SUCCESS)
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_pres.c	(revision 5241)
@@ -856,6 +856,6 @@
 
     /* Create UAS dialog: */
-    status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata, 
-				  &contact, &dlg);
+    status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata,
+					       &contact, &dlg);
     if (status != PJ_SUCCESS) {
 	pjsua_perror(THIS_FILE, 
@@ -922,8 +922,12 @@
 	}
 
+	pjsip_dlg_dec_lock(dlg);
 	PJSUA_UNLOCK();
 	pj_log_pop_indent();
 	return PJ_TRUE;
     }
+
+    /* Subscription has been created, decrement & release dlg lock */
+    pjsip_dlg_dec_lock(dlg);
 
     /* If account is locked to specific transport, then lock dialog
@@ -1036,5 +1040,4 @@
 
     /* Done: */
-
     PJSUA_UNLOCK();
     pj_log_pop_indent();
Index: pjproject/trunk/pjsip/src/test/inv_offer_answer_test.c
===================================================================
--- pjproject/trunk/pjsip/src/test/inv_offer_answer_test.c	(revision 5240)
+++ pjproject/trunk/pjsip/src/test/inv_offer_answer_test.c	(revision 5241)
@@ -309,6 +309,6 @@
 	 */
 	uri = pj_str(CONTACT);
-	status = pjsip_dlg_create_uas(pjsip_ua_instance(), rdata,
-				      &uri, &dlg);
+	status = pjsip_dlg_create_uas_and_inc_lock(pjsip_ua_instance(), rdata,
+						   &uri, &dlg);
 	pj_assert(status == PJ_SUCCESS);
 
@@ -322,4 +322,5 @@
 	status = pjsip_inv_create_uas(dlg, rdata, sdp, inv_test.param.inv_option, &inv_test.uas);
 	pj_assert(status == PJ_SUCCESS);
+	pjsip_dlg_dec_lock(dlg);
 
 	TRACE_((THIS_FILE, "    Sending 183 with SDP"));
