Hi guys! I found strange behaviour in libuv. Help me to understand is it a
bug, or something wrong with me:-)
Info:
libuv from github (master, 1.4.2, 1.x) tested with optimization and
without, in debug and in release mode
gcc version 4.9.1 (Ubuntu 4.9.1-16ubuntu6)
Ubuntu 14.10
My use case:
I want to send lots of unique uv_async_t, and all callbacks should be
invoked. So I need to have different uv_async_t for each sending.
In each callback that would be invoked I need to close a handle because
it's not need anymore.
To keep event loop running I send "blocking" uv_async_t and don't close it
to keep a handle in active state.
Strange:
I found that !sometimes! uv_run() stops.
Trying to figure out:
I started to debug my code and found that uv_run sometimes quits because
uv__loop_alive(loop) return 0.
It happens because uv__has_active_handles(loop) becomes false, due to
((loop)->active_handles > 0) condition is false.
Why the condition is false when there should be at least one active handle
in the loop, which was sent and was not closed?
It sounds like a joke, but in case uv_run don't quit the value of
loop->active_handles is about UINT_MAX!
Look the code of libuv: "unsigned int active_handles". If we have value
about UINT_MAX than we decrement this variable more than needed!
I found that there is 1 place where loop->active_handles decrements:
uv__active_handle_rm(h).
And there is 2 sequences of function invocation which lead to this call,
they are:
1. uv_run -> uv_async_close -> uv_handles_stop -> uv_active_handle_rm
2. uv_close -> uv_async_close -> uv_handles_stop -> uv_active_handle_rm
I supose that there is 2 ways why it can be:
1. libuv don't increment loop->active_handles sometimes but decrement it
2. libuv decrement loop->active_handles more than needed
Test example:
#include <uv.h>
int main()
{
uv_loop_t *loop = uv_default_loop();
// Blocking async, need to loop don't quit from run
uv_async_t async;
uv_async_init(loop, &async, [](uv_async_t* a){
std::cout << "blocking active handle\n";
// no close! it's an active handle
});
uv_async_send(&async);
// Create thread for event loop
uv_thread_t th;
uv_thread_create(&th,
[](void *arg)
{
uv_run((uv_loop_t*)arg, UV_RUN_DEFAULT);
std::cout << "Quit from event loop\n";
},
loop
); // uv_thread_create
// Send lots of async events
uv_async_t asyncs[1000];
for (int i=0; i<1000; i++)
{
asyncs[i] = uv_async_t();
uv_async_init(loop, &asyncs[i], [](uv_async_t* a)
{
std::cout << "async\n";
// async not need anymore - close it
// after that handle becomes inactive
uv_close((uv_handle_t*)a, [](uv_handle_t*)
{
// may free uv_handle_t->data here
std::cout << "close\n";
});
});
uv_async_send(&asyncs[i]);
}
uv_thread_join(&th);
return 0;
}
--
You received this message because you are subscribed to the Google Groups
"libuv" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.