Index: /pjproject/trunk/pjlib/include/pj/compat/os_win32.h
===================================================================
--- /pjproject/trunk/pjlib/include/pj/compat/os_win32.h	(revision 609)
+++ /pjproject/trunk/pjlib/include/pj/compat/os_win32.h	(revision 610)
@@ -74,5 +74,5 @@
  * the status of non-blocking connect() operation.
  */
-#define PJ_HAS_SO_ERROR             0
+#define PJ_HAS_SO_ERROR             1
 
 /* This value specifies the value set in errno by the OS when a non-blocking
Index: /pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c
===================================================================
--- /pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c	(revision 609)
+++ /pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c	(revision 610)
@@ -210,6 +210,6 @@
 	  int value;
 	  socklen_t vallen = sizeof(value);
-	  int gs_rc = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, 
-                               &value, &vallen);
+	  int gs_rc = pj_sock_getsockopt(h->fd, SOL_SOCKET, SO_ERROR, 
+					 &value, &vallen);
 	  if (gs_rc != 0) {
 	    /* Argh!! What to do now??? 
@@ -525,6 +525,18 @@
 
     /* Call callback. */
-    if (h->cb.on_connect_complete && !IS_CLOSING(h))
-	(*h->cb.on_connect_complete)(h, -1);
+    if (h->cb.on_connect_complete && !IS_CLOSING(h)) {
+	pj_status_t status = -1;
+#if (defined(PJ_HAS_SO_ERROR) && PJ_HAS_SO_ERROR!=0)
+	int value;
+	socklen_t vallen = sizeof(value);
+	int gs_rc = pj_sock_getsockopt(h->fd, SOL_SOCKET, SO_ERROR, 
+				       &value, &vallen);
+	if (gs_rc == 0) {
+	    status = PJ_RETURN_OS_ERROR(value);
+	}
+#endif
+
+	(*h->cb.on_connect_complete)(h, status);
+    }
 }
 
Index: /pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 609)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_endpoint.c	(revision 610)
@@ -283,4 +283,13 @@
 on_return:
     pj_rwmutex_unlock_write(endpt->mod_mutex);
+
+    if (status != PJ_SUCCESS) {
+	char errmsg[PJ_ERR_MSG_SIZE];
+
+	pj_strerror(status, errmsg, sizeof(errmsg));
+	PJ_LOG(3,(THIS_FILE, "Module \"%.*s\" can not be unregistered: %s",
+		  (int)mod->name.slen, mod->name.ptr, errmsg));
+    }
+
     return status;
 }
@@ -527,6 +536,9 @@
 
     /* Unregister modules. */
-    while ((mod=endpt->module_list.prev) != &endpt->module_list) {
+    mod = endpt->module_list.prev;
+    while (mod != &endpt->module_list) {
+	pjsip_module *prev = mod->prev;
 	pjsip_endpt_unregister_module(endpt, mod);
+	mod = prev;
     }
 
@@ -596,4 +608,5 @@
     pj_pool_release( pool );
 
+    PJ_UNUSED_ARG(endpt);
     /*
     pj_mutex_unlock(endpt->mutex);
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 609)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transaction.c	(revision 610)
@@ -649,4 +649,13 @@
 static pj_status_t mod_tsx_layer_unload(void)
 {
+    /* Only self destroy when there's no transaction in the table.
+     * Transaction may refuse to destroy when it has pending
+     * transmission. If we destroy the module now, application will
+     * crash when the pending transaction finally got error response
+     * from transport and when it tries to unregister itself.
+     */
+    if (pj_hash_count(mod_tsx_layer.htable) != 0)
+	return PJ_EBUSY;
+
     /* Destroy mutex. */
     pj_mutex_destroy(mod_tsx_layer.mutex);
@@ -928,4 +937,5 @@
     if (tsx->transport_flag & TSX_HAS_PENDING_TRANSPORT) {
 	tsx->transport_flag |= TSX_HAS_PENDING_DESTROY;
+	tsx->tsx_user = NULL;
 	PJ_LOG(4,(tsx->obj_name, "Will destroy later because transport is "
 				 "in progress"));
Index: /pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c
===================================================================
--- /pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c	(revision 609)
+++ /pjproject/trunk/pjsip/src/pjsip/sip_transport_tcp.c	(revision 610)
@@ -1241,4 +1241,35 @@
     tcp = pj_ioqueue_get_user_data(key);
 
+    /* Mark that pending connect() operation has completed. */
+    tcp->has_pending_connect = PJ_FALSE;
+
+    /* Check connect() status */
+    if (status != PJ_SUCCESS) {
+
+	tcp_perror(tcp->base.obj_name, "TCP connect() error", status);
+
+	/* Cancel all delayed transmits */
+	while (!pj_list_empty(&tcp->delayed_list)) {
+	    struct delayed_tdata *pending_tx;
+	    pj_ioqueue_op_key_t *op_key;
+
+	    pending_tx = tcp->delayed_list.next;
+	    pj_list_erase(pending_tx);
+
+	    op_key = (pj_ioqueue_op_key_t*)pending_tx->tdata_op_key;
+
+	    on_write_complete(tcp->key, op_key, -status);
+	}
+
+	/* We can not destroy the transport since high level objects may
+	 * still keep reference to this transport. So we can only 
+	 * instruct transport manager to gracefully start the shutdown
+	 * procedure for this transport.
+	 */
+	if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status;
+	pjsip_transport_shutdown(&tcp->base);
+	return;
+    }
+
     PJ_LOG(4,(tcp->base.obj_name, 
 	      "TCP transport %.*s:%d is connected to %.*s:%d",
@@ -1250,21 +1281,4 @@
 	      tcp->base.remote_name.port));
 
-    /* Mark that pending connect() operation has completed. */
-    tcp->has_pending_connect = PJ_FALSE;
-
-    /* Check connect() status */
-    if (status != PJ_SUCCESS) {
-
-	tcp_perror(tcp->base.obj_name, "TCP connect() error", status);
-
-	/* We can not destroy the transport since high level objects may
-	 * still keep reference to this transport. So we can only 
-	 * instruct transport manager to gracefully start the shutdown
-	 * procedure for this transport.
-	 */
-	if (tcp->close_reason==PJ_SUCCESS) tcp->close_reason = status;
-	pjsip_transport_shutdown(&tcp->base);
-	return;
-    }
 
     /* Update (again) local address, just in case local address currently
