Changeset 536 for pjproject/trunk


Ignore:
Timestamp:
Jun 22, 2006 6:41:28 PM (18 years ago)
Author:
bennylp
Message:

Fixed bug: ioqueue should return error when send()/sendto() is called while previous operation on the same op_key has not finished

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pj/ioqueue_common_abs.c

    r438 r536  
    2727 * This file is NOT supposed to be compiled as stand-alone source. 
    2828 */ 
     29 
     30#define PENDING_RETRY   2 
    2931 
    3032static void ioqueue_init( pj_ioqueue_t *ioqueue ) 
     
    281283        sent = write_op->size - write_op->written; 
    282284        if (write_op->op == PJ_IOQUEUE_OP_SEND) { 
    283             write_op->op = 0; 
    284285            send_rc = pj_sock_send(h->fd, write_op->buf+write_op->written, 
    285286                                   &sent, write_op->flags); 
     287            /* Can't do this. We only clear "op" after we're finished sending 
     288             * the whole buffer. 
     289             */ 
     290            //write_op->op = 0; 
    286291        } else if (write_op->op == PJ_IOQUEUE_OP_SEND_TO) { 
    287             write_op->op = 0; 
    288292            send_rc = pj_sock_sendto(h->fd,  
    289293                                     write_op->buf+write_op->written, 
     
    291295                                     &write_op->rmt_addr,  
    292296                                     write_op->rmt_addrlen); 
     297            /* Can't do this. We only clear "op" after we're finished sending 
     298             * the whole buffer. 
     299             */ 
     300            //write_op->op = 0; 
    293301        } else { 
    294302            pj_assert(!"Invalid operation type!"); 
     
    309317            h->fd_type == PJ_SOCK_DGRAM)  
    310318        { 
     319 
     320            write_op->op = 0; 
     321 
    311322            if (h->fd_type != PJ_SOCK_DGRAM) { 
    312323                /* Write completion of the whole stream. */ 
    313324                pj_list_erase(write_op); 
    314                 write_op->op = 0; 
    315325 
    316326                /* Clear operation if there's no more data to send. */ 
     
    663673    struct write_operation *write_op; 
    664674    pj_status_t status; 
     675    unsigned retry; 
    665676    pj_ssize_t sent; 
    666677 
     
    671682    if (key->closing) 
    672683        return PJ_ECANCELLED; 
    673  
    674     write_op = (struct write_operation*)op_key; 
    675     write_op->op = 0; 
    676684 
    677685    /* We can not use PJ_IOQUEUE_ALWAYS_ASYNC for socket write. */ 
     
    715723     * Schedule asynchronous send. 
    716724     */ 
     725    write_op = (struct write_operation*)op_key; 
     726 
     727    /* Spin if write_op has pending operation */ 
     728    for (retry=0; write_op->op != 0 && retry<PENDING_RETRY; ++retry) 
     729        pj_thread_sleep(0); 
     730 
     731    /* Last chance */ 
     732    if (write_op->op) { 
     733        /* Unable to send packet because there is already pending write in the 
     734         * write_op. We could not put the operation into the write_op 
     735         * because write_op already contains a pending operation! And 
     736         * we could not send the packet directly with send() either, 
     737         * because that will break the order of the packet. So we can 
     738         * only return error here. 
     739         * 
     740         * This could happen for example in multithreads program, 
     741         * where polling is done by one thread, while other threads are doing 
     742         * the sending only. If the polling thread runs on lower priority 
     743         * than the sending thread, then it's possible that the pending 
     744         * write flag is not cleared in-time because clearing is only done 
     745         * during polling.  
     746         * 
     747         * Aplication should specify multiple write operation keys on 
     748         * situation like this. 
     749         */ 
     750        //pj_assert(!"ioqueue: there is pending operation on this key!"); 
     751        return PJ_EBUSY; 
     752    } 
     753 
    717754    write_op->op = PJ_IOQUEUE_OP_SEND; 
    718755    write_op->buf = (void*)data; 
     
    744781{ 
    745782    struct write_operation *write_op; 
     783    unsigned retry; 
    746784    pj_status_t status; 
    747785    pj_ssize_t sent; 
     
    753791    if (key->closing) 
    754792        return PJ_ECANCELLED; 
    755  
    756     write_op = (struct write_operation*)op_key; 
    757     write_op->op = 0; 
    758793 
    759794    /* We can not use PJ_IOQUEUE_ALWAYS_ASYNC for socket write */ 
     
    791826                return status; 
    792827            } 
     828            status = status; 
    793829        } 
    794830    } 
     
    802838     * Schedule asynchronous send. 
    803839     */ 
     840    write_op = (struct write_operation*)op_key; 
     841     
     842    /* Spin if write_op has pending operation */ 
     843    for (retry=0; write_op->op != 0 && retry<PENDING_RETRY; ++retry) 
     844        pj_thread_sleep(0); 
     845 
     846    /* Last chance */ 
     847    if (write_op->op) { 
     848        /* Unable to send packet because there is already pending write on the 
     849         * write_op. We could not put the operation into the write_op 
     850         * because write_op already contains a pending operation! And 
     851         * we could not send the packet directly with sendto() either, 
     852         * because that will break the order of the packet. So we can 
     853         * only return error here. 
     854         * 
     855         * This could happen for example in multithreads program, 
     856         * where polling is done by one thread, while other threads are doing 
     857         * the sending only. If the polling thread runs on lower priority 
     858         * than the sending thread, then it's possible that the pending 
     859         * write flag is not cleared in-time because clearing is only done 
     860         * during polling.  
     861         * 
     862         * Aplication should specify multiple write operation keys on 
     863         * situation like this. 
     864         */ 
     865        //pj_assert(!"ioqueue: there is pending operation on this key!"); 
     866        return PJ_EBUSY; 
     867    } 
     868 
    804869    write_op->op = PJ_IOQUEUE_OP_SEND_TO; 
    805870    write_op->buf = (void*)data; 
Note: See TracChangeset for help on using the changeset viewer.