Search code examples
ciopthreadslibev

Weird timeout from ev_timer


Recently I was trying code libev with threads I just noticed timer always ends at near 60~ second no matter what you set it lower than 60 second. I'm not sure what causes it but I tried make code shortest possible.

1 - Call some io_init and io_start

2 - Create new thread that will call ev_loop

3 - Create timer with 5 second timeout

4 - Wait for thread to finish then main function ends

#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <ev.h>

void iocb(struct ev_loop *loop, ev_io *watcher, int flag){}

void tcb(struct ev_loop *loop, ev_timer *watcher, int flag){
    exit(0);
}

void *loop_starter(void *loop){
    ev_loop(loop, 0);
}

int main(){
    struct ev_loop *loop = ev_default_loop(0);

    ev_io evio;
    ev_io_init(&evio, iocb, 0, EV_READ);
    ev_io_start(loop, &evio);

    pthread_t pid;
    pthread_create(&pid, 0, loop_starter, loop);
    usleep(100000); /* let's be sure it entered inside ev_loop */

    ev_timer evt;
    ev_timer_init(&evt, tcb, 5, 0);
    ev_timer_start(loop, &evt);

    pthread_join(pid, 0);
}

When I run this code with time ./a.out I get

real 0m59.805s
user 0m0.000s
sys 0m0.002s

Isn't It supposed to end after 5 second? Why I get other result than 5 second?


Solution

  • We needed to implement thread mutexes or libev's ev_async functions. Here is example code that using ev_async

    #include <stdlib.h>
    #include <pthread.h>
    #include <ev.h>
    
    void iocb(struct ev_loop *loop, ev_io *watcher, int flag){}
    
    void tcb(struct ev_loop *loop, ev_timer *watcher, int flag){
        exit(0);
    }
    
    void *loop_starter(void *loop){
        ev_loop(loop, 0);
    }
    
    void async_cb(struct ev_loop *loop, ev_async *watcher, int flag){
        ev_timer *evt = malloc(sizeof(ev_timer));
        ev_timer_init(evt, tcb, 5, 0);
        ev_timer_start(loop, evt);
    }
    
    int main(){
        struct ev_loop *loop = ev_default_loop(0);
        ev_async async_w;
        ev_async_init(&async_w, async_cb);
        ev_async_start(loop, &async_w);
    
        ev_io evio;
        ev_io_init(&evio, iocb, 0, EV_READ);
        ev_io_start(loop, &evio);
    
        pthread_t pid;
        pthread_create(&pid, 0, loop_starter, loop);
        /* we don't need sleep more because */
        /* async_cb will be called from ev_loop */
    
        ev_async_send(loop, &async_w);
    
        pthread_join(pid, 0);
    }
    

    time ./a.out

    real 0m5.003s
    user 0m0.002s
    sys 0m0.000s