From 791727f49f2a8abd1e4a042581ca03e137afe3a0 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Thu, 31 Mar 2011 05:54:16 +0000 Subject: Fixed #1225: iPhone: UDP socket send error after waking up from background mode (thanks Joe Meade for the report) git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3491 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/src/pj/ioqueue_common_abs.c | 48 +++++++++++++++++++++++++++++++++++---- pjlib/src/pj/ioqueue_select.c | 3 +++ 2 files changed, 46 insertions(+), 5 deletions(-) (limited to 'pjlib') diff --git a/pjlib/src/pj/ioqueue_common_abs.c b/pjlib/src/pj/ioqueue_common_abs.c index 07ed838c..bb368ace 100644 --- a/pjlib/src/pj/ioqueue_common_abs.c +++ b/pjlib/src/pj/ioqueue_common_abs.c @@ -312,11 +312,29 @@ void ioqueue_dispatch_write_event(pj_ioqueue_t *ioqueue, pj_ioqueue_key_t *h) */ //write_op->op = 0; } else if (write_op->op == PJ_IOQUEUE_OP_SEND_TO) { - send_rc = pj_sock_sendto(h->fd, - write_op->buf+write_op->written, - &sent, write_op->flags, - &write_op->rmt_addr, - write_op->rmt_addrlen); + int retry; + for (retry=0; retry<2; ++retry) { + send_rc = pj_sock_sendto(h->fd, + write_op->buf+write_op->written, + &sent, write_op->flags, + &write_op->rmt_addr, + write_op->rmt_addrlen); +#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ + PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 + /* Special treatment for dead UDP sockets here, see ticket #1107 */ + if (send_rc==PJ_STATUS_FROM_OS(EPIPE) && !IS_CLOSING(h) && + h->fd_type==pj_SOCK_DGRAM()) + { + PJ_PERROR(4,(THIS_FILE, send_rc, + "Send error for socket %d, retrying", + h->fd)); + replace_udp_sock(h); + continue; + } +#endif + break; + } + /* Can't do this. We only clear "op" after we're finished sending * the whole buffer. */ @@ -917,12 +935,17 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key, { struct write_operation *write_op; unsigned retry; +#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ + PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 + pj_bool_t restart_retry = PJ_FALSE; +#endif pj_status_t status; pj_ssize_t sent; PJ_ASSERT_RETURN(key && op_key && data && length, PJ_EINVAL); PJ_CHECK_STACK(); +retry_on_restart: /* Check if key is closing. */ if (IS_CLOSING(key)) return PJ_ECANCELLED; @@ -959,6 +982,21 @@ PJ_DEF(pj_status_t) pj_ioqueue_sendto( pj_ioqueue_key_t *key, * the error to caller. */ if (status != PJ_STATUS_FROM_OS(PJ_BLOCKING_ERROR_VAL)) { +#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ + PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 + /* Special treatment for dead UDP sockets here, see ticket #1107 */ + if (status==PJ_STATUS_FROM_OS(EPIPE) && !IS_CLOSING(key) && + key->fd_type==pj_SOCK_DGRAM() && !restart_retry) + { + PJ_PERROR(4,(THIS_FILE, status, + "Send error for socket %d, retrying", + key->fd)); + replace_udp_sock(key); + restart_retry = PJ_TRUE; + goto retry_on_restart; + } +#endif + return status; } status = status; diff --git a/pjlib/src/pj/ioqueue_select.c b/pjlib/src/pj/ioqueue_select.c index 3125bae7..52b9ee78 100644 --- a/pjlib/src/pj/ioqueue_select.c +++ b/pjlib/src/pj/ioqueue_select.c @@ -125,7 +125,10 @@ struct pj_ioqueue_t }; /* Proto */ +#if defined(PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT) && \ + PJ_IPHONE_OS_HAS_MULTITASKING_SUPPORT!=0 static pj_status_t replace_udp_sock(pj_ioqueue_key_t *h); +#endif /* Include implementation for common abstraction after we declare * pj_ioqueue_key_t and pj_ioqueue_t. -- cgit v1.2.3