summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2017-01-11 03:35:17 +0000
committerNanang Izzuddin <nanang@teluu.com>2017-01-11 03:35:17 +0000
commit1fe4df081023310e673fd9d9949f4b54ba691731 (patch)
tree8d638e0fe3b1ca3da914f4bd24375a7c8fb90c57
parent95545ba14b27fdfd505c5c7f9f66660dba68008b (diff)
Fixed #1988: Wait for any active spinning loop in read callback to complete before reinitiating read operation in UDP restart.
git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@5519 74dad513-b988-da41-8d7b-12977e46ad98
-rw-r--r--pjsip/src/pjsip/sip_transport_udp.c41
1 files changed, 32 insertions, 9 deletions
diff --git a/pjsip/src/pjsip/sip_transport_udp.c b/pjsip/src/pjsip/sip_transport_udp.c
index 9e6d3ee5..f7b3b038 100644
--- a/pjsip/src/pjsip/sip_transport_udp.c
+++ b/pjsip/src/pjsip/sip_transport_udp.c
@@ -76,6 +76,7 @@ struct udp_transport
pjsip_rx_data **rdata;
int is_closing;
pj_bool_t is_paused;
+ int read_loop_spin;
/* Group lock to be used by UDP transport and ioqueue key */
pj_grp_lock_t *grp_lock;
@@ -129,15 +130,17 @@ static void udp_on_read_complete( pj_ioqueue_key_t *key,
int i;
pj_status_t status;
+ ++tp->read_loop_spin;
+
/* Don't do anything if transport is closing. */
if (tp->is_closing) {
tp->is_closing++;
- return;
+ goto on_return;
}
/* Don't do anything if transport is being paused. */
if (tp->is_paused)
- return;
+ goto on_return;
/*
* The idea of the loop is to process immediate data received by
@@ -227,7 +230,7 @@ static void udp_on_read_complete( pj_ioqueue_key_t *key,
* is still processing a SIP message.
*/
if (tp->is_paused)
- return;
+ break;
/* Read next packet. */
bytes_read = sizeof(rdata->pkt_info.packet);
@@ -245,6 +248,10 @@ static void udp_on_read_complete( pj_ioqueue_key_t *key,
} else if (status == PJ_EPENDING) {
break;
+ } else if (status == PJ_ECANCELLED) {
+ /* Socket is closing, quit loop */
+ break;
+
} else {
if (i < MAX_IMMEDIATE_PACKET) {
@@ -276,6 +283,9 @@ static void udp_on_read_complete( pj_ioqueue_key_t *key,
}
}
}
+
+on_return:
+ --tp->read_loop_spin;
}
/*
@@ -623,13 +633,16 @@ static pj_status_t register_to_ioqueue(struct udp_transport *tp)
if (tp->key != NULL)
return PJ_SUCCESS;
- /* Create group lock */
- status = pj_grp_lock_create(tp->base.pool, NULL, &tp->grp_lock);
- if (status != PJ_SUCCESS)
- return status;
+ /* Create group lock if not yet (don't need to do so on UDP restart) */
+ if (!tp->grp_lock) {
+ status = pj_grp_lock_create(tp->base.pool, NULL, &tp->grp_lock);
+ if (status != PJ_SUCCESS)
+ return status;
- pj_grp_lock_add_ref(tp->grp_lock);
- pj_grp_lock_add_handler(tp->grp_lock, tp->base.pool, tp, &udp_on_destroy);
+ pj_grp_lock_add_ref(tp->grp_lock);
+ pj_grp_lock_add_handler(tp->grp_lock, tp->base.pool, tp,
+ &udp_on_destroy);
+ }
/* Register to ioqueue. */
ioqueue = pjsip_endpt_get_ioqueue(tp->base.endpt);
@@ -1075,6 +1088,11 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
tp = (struct udp_transport*) transport;
+ /* Pause the transport first, so that any active read loop spin will
+ * quit as soon as possible.
+ */
+ tp->is_paused = PJ_TRUE;
+
if (option & PJSIP_UDP_TRANSPORT_DESTROY_SOCKET) {
char addr_buf[PJ_INET6_ADDRSTRLEN];
pjsip_host_port bound_name;
@@ -1138,6 +1156,11 @@ PJ_DEF(pj_status_t) pjsip_udp_transport_restart(pjsip_transport *transport,
udp_set_pub_name(tp, a_name);
}
+ /* Make sure all udp_on_read_complete() loop spin are stopped */
+ do {
+ pj_thread_sleep(1);
+ } while (tp->read_loop_spin);
+
/* Re-register new or existing socket to ioqueue. */
status = register_to_ioqueue(tp);
if (status != PJ_SUCCESS) {