Ignore:
Timestamp:
Mar 22, 2006 11:49:19 AM (19 years ago)
Author:
bennylp
Message:

Fixed bug in ioqueue with IO Completion Port backend, where events may still be called after key is unregistered

File:
1 edited

Legend:

Unmodified
Added
Removed
  • pjproject/trunk/pjlib/src/pjlib-test/ioq_udp.c

    r126 r349  
    314314} 
    315315 
     316 
     317static void on_read_complete(pj_ioqueue_key_t *key,  
     318                             pj_ioqueue_op_key_t *op_key,  
     319                             pj_ssize_t bytes_read) 
     320{ 
     321    unsigned *p_packet_cnt = pj_ioqueue_get_user_data(key); 
     322 
     323    PJ_UNUSED_ARG(op_key); 
     324    PJ_UNUSED_ARG(bytes_read); 
     325 
     326    (*p_packet_cnt)++; 
     327} 
     328 
     329/* 
     330 * unregister_test() 
     331 * Check if callback is still called after socket has been unregistered or  
     332 * closed. 
     333 */  
     334static int unregister_test(void) 
     335{ 
     336    enum { RPORT = 50000, SPORT = 50001 }; 
     337    pj_pool_t *pool; 
     338    pj_ioqueue_t *ioqueue; 
     339    pj_sock_t ssock; 
     340    pj_sock_t rsock; 
     341    int addrlen; 
     342    pj_sockaddr_in addr; 
     343    pj_ioqueue_key_t *key; 
     344    pj_ioqueue_op_key_t opkey; 
     345    pj_ioqueue_callback cb; 
     346    unsigned packet_cnt; 
     347    char sendbuf[10], recvbuf[10]; 
     348    pj_ssize_t bytes; 
     349    pj_time_val timeout; 
     350    pj_status_t status; 
     351 
     352    pool = pj_pool_create(mem, "test", 4000, 4000, NULL); 
     353    if (!pool) { 
     354        app_perror("Unable to create pool", PJ_ENOMEM); 
     355        return -100; 
     356    } 
     357 
     358    status = pj_ioqueue_create(pool, 16, &ioqueue); 
     359    if (status != PJ_SUCCESS) { 
     360        app_perror("Error creating ioqueue", status); 
     361        return -110; 
     362    } 
     363 
     364    /* Create sender socket */ 
     365    status = app_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, SPORT, &ssock); 
     366    if (status != PJ_SUCCESS) { 
     367        app_perror("Error initializing socket", status); 
     368        return -120; 
     369    } 
     370 
     371    /* Create receiver socket. */ 
     372    status = app_socket(PJ_AF_INET, PJ_SOCK_DGRAM, 0, RPORT, &rsock); 
     373    if (status != PJ_SUCCESS) { 
     374        app_perror("Error initializing socket", status); 
     375        return -130; 
     376    } 
     377 
     378    /* Register rsock to ioqueue. */ 
     379    pj_memset(&cb, 0, sizeof(cb)); 
     380    cb.on_read_complete = &on_read_complete; 
     381    packet_cnt = 0; 
     382    status = pj_ioqueue_register_sock(pool, ioqueue, rsock, &packet_cnt, 
     383                                      &cb, &key); 
     384    if (status != PJ_SUCCESS) { 
     385        app_perror("Error registering to ioqueue", status); 
     386        return -140; 
     387    } 
     388 
     389    /* Init operation key. */ 
     390    pj_ioqueue_op_key_init(&opkey, sizeof(opkey)); 
     391 
     392    /* Start reading. */ 
     393    bytes = sizeof(recvbuf); 
     394    status = pj_ioqueue_recv( key, &opkey, recvbuf, &bytes, 0); 
     395    if (status != PJ_EPENDING) { 
     396        app_perror("Expecting PJ_EPENDING, but got this", status); 
     397        return -150; 
     398    } 
     399 
     400    /* Init destination address. */ 
     401    addrlen = sizeof(addr); 
     402    status = pj_sock_getsockname(rsock, &addr, &addrlen); 
     403    if (status != PJ_SUCCESS) { 
     404        app_perror("getsockname error", status); 
     405        return -160; 
     406    } 
     407 
     408    /* Override address with 127.0.0.1, since getsockname will return 
     409     * zero in the address field. 
     410     */ 
     411    addr.sin_addr = pj_inet_addr2("127.0.0.1"); 
     412 
     413    /* Init buffer to send */ 
     414    pj_ansi_strcpy(sendbuf, "Hello0123"); 
     415 
     416    /* Send one packet. */ 
     417    bytes = sizeof(sendbuf); 
     418    status = pj_sock_sendto(ssock, sendbuf, &bytes, 0, 
     419                            &addr, sizeof(addr)); 
     420 
     421    if (status != PJ_SUCCESS) { 
     422        app_perror("sendto error", status); 
     423        return -170; 
     424    } 
     425 
     426    /* Check if packet is received. */ 
     427    timeout.sec = 1; timeout.msec = 0; 
     428    pj_ioqueue_poll(ioqueue, &timeout); 
     429 
     430    if (packet_cnt != 1) { 
     431        return -180; 
     432    } 
     433 
     434    /* Just to make sure things are settled.. */ 
     435    pj_thread_sleep(100); 
     436 
     437    /* Start reading again. */ 
     438    bytes = sizeof(recvbuf); 
     439    status = pj_ioqueue_recv( key, &opkey, recvbuf, &bytes, 0); 
     440    if (status != PJ_EPENDING) { 
     441        app_perror("Expecting PJ_EPENDING, but got this", status); 
     442        return -190; 
     443    } 
     444 
     445    /* Reset packet counter */ 
     446    packet_cnt = 0; 
     447 
     448    /* Send one packet. */ 
     449    bytes = sizeof(sendbuf); 
     450    status = pj_sock_sendto(ssock, sendbuf, &bytes, 0, 
     451                            &addr, sizeof(addr)); 
     452 
     453    if (status != PJ_SUCCESS) { 
     454        app_perror("sendto error", status); 
     455        return -200; 
     456    } 
     457 
     458    /* Now unregister and close socket. */ 
     459    pj_ioqueue_unregister(key); 
     460    pj_sock_close(rsock); 
     461 
     462    /* Poll ioqueue. */ 
     463    timeout.sec = 1; timeout.msec = 0; 
     464    pj_ioqueue_poll(ioqueue, &timeout); 
     465 
     466    /* Must NOT receive any packets after socket is closed! */ 
     467    if (packet_cnt > 0) { 
     468        PJ_LOG(3,(THIS_FILE, "....errror: not expecting to receive packet " 
     469                             "after socket has been closed")); 
     470        return -210; 
     471    } 
     472 
     473    /* Success */ 
     474    pj_sock_close(ssock); 
     475    pj_ioqueue_destroy(ioqueue); 
     476 
     477    pj_pool_release(pool); 
     478 
     479    return 0; 
     480} 
     481 
     482 
    316483/* 
    317484 * Testing with many handles. 
     
    626793    PJ_LOG(3, (THIS_FILE, "....compliance test ok")); 
    627794 
     795 
     796    PJ_LOG(3, (THIS_FILE, "...unregister test (%s)", pj_ioqueue_name())); 
     797    if ((status=unregister_test()) != 0) { 
     798        return status; 
     799    } 
     800    PJ_LOG(3, (THIS_FILE, "....unregister test ok")); 
     801 
    628802    if ((status=many_handles_test()) != 0) { 
    629803        return status; 
Note: See TracChangeset for help on using the changeset viewer.