[Info-vax] Problems with multithreaded calls to libCURL
Jim Duff
jim at send.spam.here
Thu Mar 7 18:09:33 EST 2019
Versions:
OpenVMS 8.4 on IA64
HP C V7.2-001:
libCURL: 7.4.7
Nearly seven years ago, I wrote some code to utilise libCURL to perform
FTP for a document routing system. The code was single threaded, and it
quickly became the event driven successor for what was then a polling
system based on CIFS.
Today, the system ships hundreds of thousands of documents a day off the
central ERP system. All usually goes well, but there is at least one
problem that can seriously impact document delivery times. This occurs
when an FTP server at a target machine is unavailable.
When this occurs, with the default setting of CURLOPT_CONNECTTIMEOUT, a
5 minute delay can occur as the library waits for the connection to
complete. Easy fix says I, just set CURLOPT_CONNECTIMEOUT to a smaller
value with a call like
res = curl_easy_setopt (handle, CURLOPT_CONNECTTIMEOUT, 30L);
for a 30 second timeout.
Except this appears to have no effect.
After double checking that no later version of libCURL is currently
available for OpenVMS, I embarked on multithreading the code so that
there would be one worker thread per server and target directory
combination. That way, if an FTP server was unavailable, only documents
destined for that server would be impacted by the connect timeout issue
as only the affected thread(s) would stall.
To my consternation, on stress testing the multithreaded code, I'm
occasionally getting an access violation in the depths of libCURL:
%SYSTEM-F-ACCVIO, access violation, reason mask=00, virtual
address=000000000000
0028, PC=FFFFFFFF84088EB0, PS=0000001B
%TRACE-F-TRACEBACK, symbolic stack dump follows
image module routine line rel PC abs PC
LIBRTL LIB$$UNWIND restoreReg 22380 00000000000007A0
FFFFFFFF84088EB0
LIBRTL LIB$$UNWIND step_final_phase 25871 0000000000010652
FFFFFFFF84098D62
LIBRTL LIB$$UNWIND UC_step 24860 000000000000C682
FFFFFFFF84094D92
LIBRTL LIB$$UNWIND UC_currentContext
21987 0000000000000602
FFFFFFFF84088D12
LIBRTL LIB$IPF_CALLING_STANDARD lib$i64_get_curr_invo_context
19476 00000000000009A2
FFFFFFFF8407FAB2
DECC$SHR C$SETJMP sigsetjmp 17136 00000000000008B2
FFFFFFFF84B6DBE2
GNV$LIBCURL hostip Curl_resolv_timeout
82084 0000000000001382
000000000020E322
GNV$LIBCURL url create_conn 92703 00000000000145E2
00000000001FFDD2
GNV$LIBCURL url Curl_connect 93456 0000000000014D12
0000000000200502
GNV$LIBCURL multi multi_runsingle 83372 0000000000003002
00000000001DCF62
GNV$LIBCURL multi curl_multi_perform
84076 0000000000006C52
00000000001E0BB2
GNV$LIBCURL easy curl_easy_perform 87297 0000000000000C52
00000000001CCC52
FTP_SENDER FTP_SENDER do_ftp 62939 00000000000027C2
00000000000227C2
FTP_SENDER FTP_SENDER worker 63195 00000000000047D2
00000000000247D2
PTHREAD$RTL THD_THREAD thdBase 245274 0000000000005C52
FFFFFFFF844D4ED2
PTHREAD$RTL 0 0000000000054012
FFFFFFFF844AE012
PTHREAD$RTL THD_INIT pthread_main 244961 0000000000000492
FFFFFFFF8448A492
0 FFFFFFFF80B026D2
FFFFFFFF80B026D2
DCL 0 000000000007D072
000000007AE21072
%TRACE-I-END, end of TRACE stack dump
Enclosing the calls to curl_easy_perform () in a mutex makes the access
violation go away, making me think that libCURL's claim to being thread
safe is not so rock solid.
Reading https://curl.haxx.se/libcurl/c/threadsafe.html I see there are
some exceptions to its thread safe claim, so I duly implemented them:
1) don't share handles between threads. I wasn't doing this in the
first place.
2) I'm not using the share interface.
3) disable signals with CURLOPT_NOSIGNAL set to 1L
4) call curl_global_init () in the main thread before creating
additional threads.
5) don't use CURLOPT_DNS_USE_GLOBAL_CACHE. I wasn't.
I'd love to debug this myself, but I have so much on my plate that I
have no time to do so.
If anyone has any ideas, or has implemented a multithreaded system
employing libCURL, I'd love to hear from you.
Jim
More information about the Info-vax
mailing list