libuv/libcurl downloading example with threaded adding new download requests

674 views
Skip to first unread message

Przemysław Sobala

unread,
May 23, 2017, 8:28:17 AM5/23/17
to libuv
Hello
I've modified a https://github.com/curl/curl/blob/master/docs/examples/multi-uv.c example to support adding new download requests via multiple threads.

My design is this:

1) In main thread I setup and run uv_loop_t:
loop_mutex.lock();
uv_run(loop, UV_RUN_DEFAULT);
loop_mutex.unlock();
but to prevent this loop from quitting in the same thread I'm adding an async handle:
uv_async_init(loop, &loop_wakup, NULL);

2) A thread can add a new downloading requrst by calling the Add method:
void FileDownloader::Add(const string url, const string file_path,
done_callback_t done_cb, 
error_callback_t error_cb) {
curl_easy_ctx *easy_ctx = new curl_easy_ctx();
easy_ctx->done_callback = done_cb;
easy_ctx->error_callback = error_cb;
easy_ctx->file = unique_ptr<File>(new File(file_path));
CURL *handle = curl_easy_init();
// downloaded data will be written to file
curl_easy_setopt(handle, CURLOPT_WRITEDATA, easy_ctx->file->InternalHandle());
// private single downloading context
curl_easy_setopt(handle, CURLOPT_PRIVATE, easy_ctx);
// fail if http response code is >= 400
curl_easy_setopt(handle, CURLOPT_FAILONERROR, 1);
// follow redirects
curl_easy_setopt(handle, CURLOPT_FOLLOWLOCATION, 1);
// whole request timeout [sec]
curl_easy_setopt(handle, CURLOPT_TIMEOUT, req_timeout);
// URL to download
curl_easy_setopt(handle, CURLOPT_URL, url.c_str());
// disable signal handlers
curl_easy_setopt(handle, CURLOPT_NOSIGNAL, 1L);
synchronized(curl_handle_mutex) {
curl_multi_add_handle(curl_handle, handle);
}
uv_async_send(&loop_wakup);
LOG(INFO) << "Downloading " << url << " -> " << file_path;
}
as you can see, after adding new curl easy handle I'm waking up the uv loop by calling uv_async_send

Is this design correct?

Saúl Ibarra Corretgé

unread,
May 23, 2017, 10:48:46 AM5/23/17
to li...@googlegroups.com
I don't think so. With your design other threads will have to wait for
the loop to finish running (which will never happen if you have an
unref'd async handle) before they can call curl_multi_add_handle, thus
making the point of using multiple threads (if that's what you wanted
to do) moot.

What you can do instead is store the new curl handle in a QUEUE which
you protect with a mutex, and wakeup the loop. Then in the async
callback call curl_multi_add_handle for each curl handle in the queue.


Cheers,

--
/Saúl
bettercallsaghul.com

Przemysław Sobala

unread,
May 23, 2017, 12:07:11 PM5/23/17
to libuv
Hi Saul 

I've though of that. My flow is as follows:
1) initialization of uv_loop_t and curl_multi handle
2) running mentioned uv_loop_t in separate thread - endlessly by adding an async handle
3) "client" threads are calling Add method (it's body is in the first post)

It seems to do it's job, do you have any comments on that?

--
regards
Przemysław Sobala

Saúl Ibarra Corretgé

unread,
May 23, 2017, 12:09:10 PM5/23/17
to li...@googlegroups.com
On Tue, May 23, 2017 at 5:45 PM, Przemysław Sobala
I don't see how :-) Given the loop thread takes the lock before
calling uv_run, and uv_run runs endlessly, when will it let go fo the
lock?

--
/Saúl
bettercallsaghul.com

Przemysław Sobala

unread,
May 24, 2017, 4:10:52 AM5/24/17
to libuv
another thread can call
uv_stop(loop);
uv_async_send
(&loop_wakeup);
// wait for loop to successfully close
loop_mutex.lock();

then it blocks on loop_mutex.lock() and waits for uv_run to exit and release (unlock) the loop_mutex, after that it exists as well.

Ben Noordhuis

unread,
May 24, 2017, 4:48:01 AM5/24/17
to li...@googlegroups.com
On Wed, May 24, 2017 at 10:10 AM, Przemysław Sobala
<przemysl...@gmail.com> wrote:
> another thread can call
> uv_stop(loop);
> uv_async_send(&loop_wakeup);
> // wait for loop to successfully close
> loop_mutex.lock();
>
> then it blocks on loop_mutex.lock() and waits for uv_run to exit and release
> (unlock) the loop_mutex, after that it exists as well.

Other threads aren't allowed to call uv_stop(), only uv_async_send().

Przemysław Sobala

unread,
May 24, 2017, 5:01:17 AM5/24/17
to libuv
Thanks! I'll take care of that. 

Przemysław Sobala

unread,
May 24, 2017, 8:50:27 AM5/24/17
to libuv
Hi, under some stress (10 downlaoding requests per sec) my program (described in this thread) occasionally crashes with segmentation fault (SIGSEGV).

Can you help me resolve this issue?

(gdb) info threads  
 
Id   Target Id         Frame  
* 1    Thread 0x7f58cffff700 (LWP 10505) 0x00007f58ea4a8765 in raise () from /lib64/libc.so.6
 
2    Thread 0x7f58ec434980 (LWP 10496) 0x00007f58ea842bd0 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
 
3    Thread 0x7f58e6e56700 (LWP 10500) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6
 
4    Thread 0x7f58e7e58700 (LWP 10498) 0x00007f58ea845afd in __lll_lock_wait () from /lib64/libpthread.so.0
 
5    Thread 0x7f58e8659700 (LWP 10497) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6
 
6    Thread 0x7f58cf7fe700 (LWP 10506) 0x00007f58ea56722d in write () from /lib64/libc.so.6
 
7    Thread 0x7f58e7657700 (LWP 10499) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6
 
8    Thread 0x7f58e6655700 (LWP 10501) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6
 
9    Thread 0x7f58e5e54700 (LWP 10502) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6
 
10   Thread 0x7f58e4e52700 (LWP 10504) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6
 
11   Thread 0x7f58e5653700 (LWP 10503) 0x00007f58ea577307 in epoll_pwait () from /lib64/libc.so.6

thread 1 stack:
#0  0x00007f58ea4a8765 in raise () from /lib64/libc.so.6
#1  0x00007f58ea4aa483 in abort () from /lib64/libc.so.6
#2  0x00000000004b7a23 in MagickPanicSignalHandler (signo=11) at magick/magick.c:835
#3  <signal handler called>
#4  0x0000000000813162 in heap_remove (less_than=0x812fc0 <timer_less_than>, node=0x7ffddd63ec98, heap=0xc28a28 <default_loop_struct+520>) at ./src/heap-inl.h:187
#5  uv_timer_stop (handle=0x7ffddd63ec30) at src/unix/timer.c:97
#6  0x000000000081341d in uv_timer_start (handle=0xffffffffffffff98, cb=<optimized out>, timeout=<optimized out>, repeat=<optimized out>) at src/unix/timer.c:87
#7  0x00007ffddd63ebf0 in ?? ()
#8  0x0000000000417c74 in imageresizer::engine::FileDownloader::start_timeout (this=0x1f1, multi=0x7f58eb73ca60, timeout_ms=140019881360094) at src/engine/FileDownloader.cpp:249
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
In the same project I'm using GraphicsMagick that registers its own signal handler hence frame #2, but still it looks like uv_timer_stop throws SIGSEGV

thread 2 is gRPC server thread, thread 3 is gRPC's completion queue thread

thread 4 is locked on curl multi handle during on_timeout callback:
(gdb) bt
#0  0x00007f58ea845afd in __lll_lock_wait () from /lib64/libpthread.so.0
#1  0x00007f58ea83fa0d in pthread_mutex_lock () from /lib64/libpthread.so.0
#2  0x0000000000416d81 in __gthread_mutex_lock (__mutex=0x7ffddd63ed70) at /usr/include/c++/6.3.1/x86_64-redhat-linux/bits/gthr-default.h:748
#3  0x0000000000418032 in std::mutex::lock (this=0x7ffddd63ed70) at /usr/include/c++/6.3.1/bits/std_mutex.h:101
#4  0x0000000000418209 in imageresizer::util::Lock::Lock (this=0x7f58e7e57a70, m=...) at ./src/util/Lock.h:21
#5  0x0000000000417b77 in imageresizer::engine::FileDownloader::on_timeout (this=0x7ffddd63ebf0, handle=0x7ffddd63ec30) at src/engine/FileDownloader.cpp:230
#6  0x0000000000417b48 in imageresizer::engine::FileDownloader::on_timeout_cb (handle=0x7ffddd63ec30) at src/engine/FileDownloader.cpp:223
#7  0x0000000000813515 in uv__run_timers (loop=0x7ffddd63ed70) at src/unix/timer.c:159
#8  0x000000000080bf3c in uv__update_time (loop=0xc28820 <default_loop_struct>) at src/unix/internal.h:316
#9  uv_run (loop=0xc28820 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:342
#10 0x0000000000417474 in imageresizer::engine::FileDownloader::StartLoop (this=0x7ffddd63ebf0) at src/engine/FileDownloader.cpp:96
#11 0x000000000041979a in std::__invoke_impl<void, void (imageresizer::engine::FileDownloader::* const&)(), imageresizer::engine::FileDownloader*>(std::__invoke_memfun_deref, void (imageresizer::engine::FileDownloader::* const&)(), image
resizer
::engine::FileDownloader*&&) (
    __f
=@0x1a323f0: (void (imageresizer::engine::FileDownloader::*)(imageresizer::engine::FileDownloader * const)) 0x4173e4 <imageresizer::engine::FileDownloader::Add(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocato
r
<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void ()>, std::function<void (imageresizer::DownloadFileError const&)>)+670>,  
    __t
=<unknown type in /opt/WP/imageresizer-worker/dist/Debug/GNU-Linux/imageresizer-worker, CU 0x1cd0b, DIE 0x2a784>) at /usr/include/c++/6.3.1/functional:227
#12 0x0000000000419727 in std::__invoke<void (imageresizer::engine::FileDownloader::* const&)(), imageresizer::engine::FileDownloader*>(void (imageresizer::engine::FileDownloader::* const&)(), imageresizer::engine::FileDownloader*&&) (
    __fn
=@0x1a323f0: (void (imageresizer::engine::FileDownloader::*)(imageresizer::engine::FileDownloader * const)) 0x4173e4 <imageresizer::engine::FileDownloader::Add(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocat
or<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::function<void ()>, std::function<void (imageresizer::DownloadFileError const&)>)+670>,  
    __args
#0=<unknown type in /opt/WP/imageresizer-worker/dist/Debug/GNU-Linux/imageresizer-worker, CU 0x1cd0b, DIE 0x2a784>) at /usr/include/c++/6.3.1/functional:251
#13 0x00000000004196d8 in std::_Mem_fn_base<void (imageresizer::engine::FileDownloader::*)(), true>::operator()<imageresizer::engine::FileDownloader*>(imageresizer::engine::FileDownloader*&&) const (this=0x1a323f0,  
    __args
#0=<unknown type in /opt/WP/imageresizer-worker/dist/Debug/GNU-Linux/imageresizer-worker, CU 0x1cd0b, DIE 0x2a784>) at /usr/include/c++/6.3.1/functional:604
#14 0x00000000004196a3 in std::_Bind_simple<std::_Mem_fn<void (imageresizer::engine::FileDownloader::*)()> (imageresizer::engine::FileDownloader*)>::_M_invoke<0ul>(std::_Index_tuple<0ul>) (this=0x1a323e8)
    at
/usr/include/c++/6.3.1/functional:1390
#15 0x00000000004195f1 in std::_Bind_simple<std::_Mem_fn<void (imageresizer::engine::FileDownloader::*)()> (imageresizer::engine::FileDownloader*)>::operator()() (this=0x1a323e8) at /usr/include/c++/6.3.1/functional:1380
#16 0x00000000004195d0 in std::thread::_State_impl<std::_Bind_simple<std::_Mem_fn<void (imageresizer::engine::FileDownloader::*)()> (imageresizer::engine::FileDownloader*)> >::_M_run() (this=0x1a323e0)
    at
/usr/include/c++/6.3.1/thread:196
#17 0x00007f58eb02d5cf in ?? () from /lib64/libstdc++.so.6
#18 0x00007f58ea83d5ca in start_thread () from /lib64/libpthread.so.0
#19 0x00007f58ea5770ed in clone () from /lib64/libc.so.6

thread 6 is writing using Google Log (glog) framework.
Other threads are waiting for client downloading requests.
Threads 4-11 are client threads.

Can you help me debug this probl

Przemysław Sobala

unread,
May 24, 2017, 9:14:26 AM5/24/17
to libuv

    __fn
=@0x1a323f0: (void (imageresizer::engine::FileDownloader<span

I've  commented out logging, so they don't interfere, and know i don't know what to say. Just look at this:
(gdb) info threads  
 
Id   Target Id         Frame  
* 1    Thread 0x7f1c5550f700 (LWP 10974) 0x00007f1c57b5f765 in raise () from /lib64/libc.so.6
 
2    Thread 0x7f1c59aeb980 (LWP 10972) 0x00007f1c57ef9bd0 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
 
3    Thread 0x7f1c55d10700 (LWP 10973) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
4    Thread 0x7f1c4ffff700 (LWP 10976) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
5    Thread 0x7f1c4effd700 (LWP 10978) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
6    Thread 0x7f1c4d7fa700 (LWP 10981) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
7    Thread 0x7f1c4dffb700 (LWP 10980) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
8    Thread 0x7f1c4f7fe700 (LWP 10977) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
9    Thread 0x7f1c4e7fc700 (LWP 10979) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
10   Thread 0x7f1c54d0e700 (LWP 10975) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6
 
11   Thread 0x7f1c4cff9700 (LWP 10982) 0x00007f1c57c2e307 in epoll_pwait () from /lib64/libc.so.6

(gdb) bt
#0  0x00007f1c57b5f765 in raise () from /lib64/libc.so.6
#1  0x00007f1c57b61483 in abort () from /lib64/libc.so.6
#2  0x00000000004b7a23 in GetMagickInfoArray (exception=0xc28820 <default_loop_ptr>) at magick/magick.c:548
#3  0x0000000000000000 in ?? ()
GraphicsMagick is being linked in staticly but no GraphicsMagick code is being invoked during my stress test, only libuv and libcurl functions.
Can you tell me what am I missing here?

Przemysław Sobala

unread,
May 24, 2017, 9:39:45 AM5/24/17
to libuv
 Another stack. Maybe that one will be more clear to you:
(gdb) bt
#0  0x00007efd3665a765 in raise () from /lib64/libc.so.6
#1  0x00007efd3665c483 in abort () from /lib64/libc.so.6
#2  0x00000000004b79b3 in MagickPanicSignalHandler (signo=11) at magick/magick.c:840
#3  <signal handler called>
#4  heap_insert (less_than=0x812f40 <timer_less_than>, newnode=0x7ffd799e8ab8, heap=0xc28a28 <default_loop_struct+520>) at ./src/heap-inl.h:140
#5  uv_timer_start (handle=0x7ffd799e8a50, cb=0x417abe <imageresizer::engine::FileDownloader::on_timeout_cb(uv_timer_s*)>, timeout=<optimized out>, repeat=0) at src/unix/timer.c:84
#6  0x0000000000417c0c in imageresizer::engine::FileDownloader::start_timeout (this=0x7ffd799e8a10, multi=0x2c0cdd0, timeout_ms=96) at src/engine/FileDownloader.cpp:249
#7  0x0000000000417baf in imageresizer::engine::FileDownloader::start_timeout_cb (multi=0x2c0cdd0, timeout_ms=96, userp=0x7ffd799e8a10) at src/engine/FileDownloader.cpp:237
#8  0x00000000007c7665 in update_timer ()
#9  0x00000000007cb098 in curl_multi_socket_action ()
#10 0x0000000000417b3f in imageresizer::engine::FileDownloader::on_timeout (this=0x7ffd799e8a10, handle=0x7ffd799e8a50) at src/engine/FileDownloader.cpp:231
#11 0x0000000000417ae0 in imageresizer::engine::FileDownloader::on_timeout_cb (handle=0x7ffd799e8a50) at src/engine/FileDownloader.cpp:223
#12 0x00000000008134a5 in uv__run_timers (loop=loop@entry=0xc28820 <default_loop_struct>) at src/unix/timer.c:165
#13 0x000000000080becc in uv_run (loop=0xc28820 <default_loop_struct>, mode=UV_RUN_DEFAULT) at src/unix/core.c:343
#14 0x0000000000417409 in imageresizer::engine::FileDownloader::StartLoop (this=0x7ffd799e8a10) at src/engine/FileDownloader.cpp:97


Ben Noordhuis

unread,
May 24, 2017, 10:07:41 AM5/24/17
to li...@googlegroups.com
Looks like memory corruption or maybe a data race. Give valgrind a go.

Przemysław Sobala

unread,
May 24, 2017, 11:32:43 AM5/24/17
to libuv
Unfortunately, running a stress test under valgrind does not make my program quit with SIGSEGV :-( 

Jameson Nash

unread,
May 25, 2017, 2:02:35 PM5/25/17
to libuv
Maybe try `rr` with chaos mode instead?

--
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 libuv+un...@googlegroups.com.
To post to this group, send email to li...@googlegroups.com.
Visit this group at https://groups.google.com/group/libuv.
For more options, visit https://groups.google.com/d/optout.

Przemysław Sobala

unread,
Jun 2, 2017, 9:33:24 AM6/2/17
to libuv
I'm about to compile and try rr. Meanwhile I've run my code in the production environment and caught some segmentation faults. I'd be pleased if you take a look: https://docs.google.com/document/d/1hOX9FLcx5N6gdLQ-aAMwNpPqCzpfXqDKjNaHqFGGbSY/edit?usp=sharing

Przemysław Sobala

unread,
Jun 5, 2017, 5:49:53 AM6/5/17
to libuv
W dniu piątek, 2 czerwca 2017 15:33:24 UTC+2 użytkownik Przemysław Sobala napisał:
I'm about to compile and try rr. Meanwhile I've run my code in the production environment and caught some segmentation faults. I'd be pleased if you take a look: https://docs.google.com/document/d/1hOX9FLcx5N6gdLQ-aAMwNpPqCzpfXqDKjNaHqFGGbSY/edit?usp=sharing

I've reviewed my design and revealed a potential flaw.
As you can see in post #1 I've got 1 main thread with uv_loop running continuously and request accepting threads that call curl_multi_add_handle.
It turns out that curl_multi_add_handle calls start_timeout callback function (see https://github.com/curl/curl/blob/master/docs/examples/multi-uv.c) that calls uv_timer_start and uv_timer_stop.
This log confirms that:
                    <thread id>
I0605 11:46:54.860105 22880 FileDownloader.cpp:107] File downloading loop started
I0605 11:47:03.028491 22883 FileDownloader.cpp:254] start timeout 0ms
I0605 11:47:03.028506 22883 FileDownloader.cpp:265] /start timeout
I0605 11:47:03.028512 22883 FileDownloader.cpp:103] Downloading http://i.wp.pl/a/f/jpeg/37211/sarah-cover-photo-1280x.jpeg?i=0 -> /tmp/ir.download
I0605 11:47:03.029150 22880 FileDownloader.cpp:273] handle_socket (action: 2, socket: 0)
I0605 11:47:03.029168 22880 FileDownloader.cpp:303] /handle_socket
I0605 11:47:03.029171 22880 FileDownloader.cpp:254] start timeout 0ms
I0605 11:47:03.029173 22880 FileDownloader.cpp:265] /start timeout
I0605 11:47:03.030094 22880 FileDownloader.cpp:273] handle_socket (action: 1, socket: 0x7fc9d0002920)
I0605 11:47:03.030102 22880 FileDownloader.cpp:303] /handle_socket
I0605 11:47:03.030105 22880 FileDownloader.cpp:254] start timeout 199ms
I0605 11:47:03.030107 22880 FileDownloader.cpp:265] /start timeout
I0605 11:47:03.047816 22880 FileDownloader.cpp:273] handle_socket (action: 4, socket: 0x7fc9d0002920)
I0605 11:47:03.047832 22880 FileDownloader.cpp:303] /handle_socket
I0605 11:47:03.047835 22880 FileDownloader.cpp:192] Finished http://i.wp.pl/a/f/jpeg/37211/sarah-cover-photo-1280x.jpeg?i=0 (0 - No error, code: 200, time: 19.287 ms, speed: 250303 kb/s)
I0605 11:47:03.047858 22880 FileDownloader.cpp:254] start timeout -1ms
I0605 11:47:03.047863 22880 FileDownloader.cpp:265] /start timeout

If I understand correctly these functions cannot be called simultaneously from other threads with running uv_loop in main thread.
How can I fix that? Should I use uv_async_send() to call uv_timer_start() and uv_timer_stop()?

--
Regards
Przemysław Sobala

Saúl Ibarra Corretgé

unread,
Jun 5, 2017, 11:25:00 AM6/5/17
to li...@googlegroups.com
I suggest you re-read my suggestion a few emails back. Move handling of the entire curl handle to the uv thread with a queue, a muted and an async handle.


-Saúl

Przemysław Sobala

unread,
Jun 5, 2017, 11:55:00 AM6/5/17
to libuv
W dniu poniedziałek, 5 czerwca 2017 17:25:00 UTC+2 użytkownik Saúl Ibarra Corretgé napisał:
I suggest you re-read my suggestion a few emails back. Move handling of the entire curl handle to the uv thread with a queue, a muted and an async handle.


-Saúl

Hello Saúl
Thanks for still being here :-) 

If I understood correctly, I did something like this:

(inside the thread that should add a downloading request to uv_loop)
synchronized(request_queue_mutex) {
request_queue.data = curl_easy_handle;
uv_queue_work(loop, &request_queue,
[](uv_work_t* req) {},
[](uv_work_t* req, int status) {
LOG(INFO) << "working done: ";
curl_multi_add_handle(curl_handle, (CURL *) req->data);
});
}

but after running 2 simultaneous request my code breaks with:
==18186== Process terminating with default action of signal 6 (SIGABRT): dumping core
==18186==    at 0x687C765: raise (in /usr/lib64/libc-2.23.so)
==18186==    by 0x687E482: abort (in /usr/lib64/libc-2.23.so)
==18186==    by 0x4B7D52: MagickPanicSignalHandler (magick.c:840)
==18186==    by 0x663CC2F: ??? (in /usr/lib64/libpthread-2.23.so)
==18186==    by 0xC29997: ???
==18186==    by 0x80A30B: uv__work_done (threadpool.c:245)
==18186==    by 0x80C0FA: uv__async_io (async.c:118)
==18186==    by 0x8161F7: uv__io_poll (linux-core.c:400)
==18186==    by 0x80C923: uv_run (core.c:359)
==18186==    by 0x41768C: imageresizer::engine::FileDownloader::StartLoop() (FileDownloader.cpp:103)
==18186==    by 0x4199A3: void std::__invoke_impl<void, void (imageresizer::engine::FileDownloader::* const&)(), imageresizer::engine::FileDownloader*>(std::__invoke_memfun_deref, void (imageresizer::engine::FileDownloader::* const&)(),
imageresizer::engine::FileDownloader*&&) (functional:227)
==18186==    by 0x419930: std::result_of<void (imageresizer::engine::FileDownloader::* const&(imageresizer::engine::FileDownloader*&&))()>::type std::__invoke<void (imageresizer::engine::FileDownloader::* const&)(), imageresizer::engine:
:FileDownloader*>(void (imageresizer::engine::FileDownloader::* const&)(), imageresizer::engine::FileDownloader*&&) (functional:251)
--
regards
Przemysław Sobala

Saúl Ibarra Corretgé

unread,
Jun 6, 2017, 10:09:47 AM6/6/17
to li...@googlegroups.com
I never said you should use uv_queue_work :-) The work item will be
called in a different thread, so you're back to undefined behavior!

You must make the curl_multi_add_handle function run in the loop
thread. An async handle could help you with that. But watch out with
where you call uv_async_init, only, I repeat *ONLY* uv_async_send is
thread-safe.


Cheers,
> --
> 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 libuv+un...@googlegroups.com.
> To post to this group, send email to li...@googlegroups.com.
> Visit this group at https://groups.google.com/group/libuv.
> For more options, visit https://groups.google.com/d/optout.



--
/Saúl
bettercallsaghul.com

Przemysław Sobala

unread,
Jun 7, 2017, 10:20:51 AM6/7/17
to libuv
You must make the curl_multi_add_handle function run in the loop
thread. An async handle could help you with that. But watch out with
where you call uv_async_init, only, I repeat *ONLY* uv_async_send is
thread-safe.

That was it!
Thanks!
I used std::queue with mutexes.
Now I'm searching the web for some lock-free concurent queue. 
--
regards
Przemysław Sobal
Reply all
Reply to author
Forward
0 new messages