On 04/17/2015 11:47 AM, Denis Shilkin wrote: > 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. >
What do you mean by "blocking" here? You just keep an async handle around?
> Strange:
> I found that !sometimes! uv_run() stops.
>
Do you unref the handle? Do you call uv_stop?
> 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!
How may async handles are you creating? Maybe you created an overflow.
>
> 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;
> }
>
Ah, I see now. You are calling uv_async_init in another thread. THat's
not safe. *Only* uv_async_send is.
Regards,
--
Saúl Ibarra Corretgé
bettercallsaghul.com
--
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.
signature.asc
Description: OpenPGP digital signature
