caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Multithreaded https requests in ocamlnet netclient
@ 2012-11-27  2:54 Mike Lin
  2012-11-27 13:03 ` [Caml-list] AW: " Gerd Stolpmann
  0 siblings, 1 reply; 4+ messages in thread
From: Mike Lin @ 2012-11-27  2:54 UTC (permalink / raw)
  To: Gerd Stolpmann, ocamlnet-devel, caml-list

[-- Attachment #1: Type: text/plain, Size: 825 bytes --]

Hello Gerd, all,

I'm trying to find the right incantations to make parallel https requests
from multiple threads using Http_client. (I know the library is capable of
multiple requests from one thread -- I have other strong reasons to use
multithreading.)

https://gist.github.com/4152047

This program generally segfaults for me at some random point during the 10
requests.  Compiled as in the comment in line 2 (ubuntu quantal,
libocamlnet-ocaml-dev 3.5.1, ocaml 3.12.1).

Permutations attempted:

1) Change https to http in google URL -- works as expected
2) Serialize requests by uncommenting line 35 -- works as expected
3) Move invocations of Ssl.init, Ssl.create_context,
HTTPS.https_transport_channel_type in and out of fresh_pipeline (which runs
in the worker threads) -- no help

Any suggestions? Thanks!

Mike Lin

[-- Attachment #2: Type: text/html, Size: 1099 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Caml-list] AW: Multithreaded https requests in ocamlnet netclient
  2012-11-27  2:54 [Caml-list] Multithreaded https requests in ocamlnet netclient Mike Lin
@ 2012-11-27 13:03 ` Gerd Stolpmann
  2012-11-28  1:43   ` [Caml-list] " Mike Lin
  0 siblings, 1 reply; 4+ messages in thread
From: Gerd Stolpmann @ 2012-11-27 13:03 UTC (permalink / raw)
  To: Mike Lin; +Cc: ocamlnet-devel, caml-list

Hi Mike,

I can confirm the problem, but I'm not able to track it down.

First of all, I'm quite sure that you cannot share SSL contexts between  
threads. But even if I fix this, I get crashes - usually early during  
SSL_connect.

I'm wondering whether ocaml-ssl initializes openssl correctly for  
multi-threading. In my version of openssl the prototype is

int CRYPTO_THREADID_set_callback(void (*threadid_func)(CRYPTO_THREADID  
*));

but in ocaml-ssl the CRYPTO_THREADID pointer is ignored (it assumes  
void here). So, maybe this is the reason. I currently don't have time  
to follow this idea.

If everything fails, there is a way to use Netclient in threaded  
applications so that only one thread is doing the networking stuff, see  
this example:

https://godirepo.camlcity.org/svn/lib-ocamlnet2/trunk/code/examples/netclient/simple/http_mt.ml

As Netclient is event-driven, the requests are processed in parallel  
(with one exception, though: DNS lookups are synchronous, but this can  
be worked around, as the DNS lookup function is settable in Netclient).

Gerd

Am 27.11.2012 03:54:16 schrieb(en) Mike Lin:
> Hello Gerd, all,
> 
> I'm trying to find the right incantations to make parallel https  
> requests
> from multiple threads using Http_client. (I know the library is  
> capable of
> multiple requests from one thread -- I have other strong reasons to  
> use
> multithreading.)
> 
> https://gist.github.com/4152047
> 
> This program generally segfaults for me at some random point during  
> the 10
> requests.  Compiled as in the comment in line 2 (ubuntu quantal,
> libocamlnet-ocaml-dev 3.5.1, ocaml 3.12.1).
> 
> Permutations attempted:
> 
> 1) Change https to http in google URL -- works as expected
> 2) Serialize requests by uncommenting line 35 -- works as expected
> 3) Move invocations of Ssl.init, Ssl.create_context,
> HTTPS.https_transport_channel_type in and out of fresh_pipeline  
> (which runs
> in the worker threads) -- no help
> 
> Any suggestions? Thanks!
> 
> Mike Lin
> 



-- 
------------------------------------------------------------
Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
Creator of GODI and camlcity.org.
Contact details:        http://www.camlcity.org/contact.html
Company homepage:       http://www.gerd-stolpmann.de
------------------------------------------------------------

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Caml-list] Re: Multithreaded https requests in ocamlnet netclient
  2012-11-27 13:03 ` [Caml-list] AW: " Gerd Stolpmann
@ 2012-11-28  1:43   ` Mike Lin
  2013-09-26  8:34     ` [Caml-list] " Török Edwin
  0 siblings, 1 reply; 4+ messages in thread
From: Mike Lin @ 2012-11-28  1:43 UTC (permalink / raw)
  To: Gerd Stolpmann; +Cc: ocamlnet-devel, caml-list

[-- Attachment #1: Type: text/plain, Size: 3221 bytes --]

Thanks, Gerd!

FWIW I could not reproduce the crash by using ocaml-ssl's blocking
operations directly.

https://gist.github.com/4152047#file_ssl_threads.ml

This works fine- so, perhaps something nasty arises from using nonblocking
I/O on ssl sockets from multiple threads. I'm sure if there is any other
critical difference with how netclient/equeue-ssl and my example use
ocaml-ssl.

I also don't have time to pursue this much further, so I will try to put
all of my http operations on one thread as your example suggests.

Best,
Mike


On Tue, Nov 27, 2012 at 5:03 AM, Gerd Stolpmann <info@gerd-stolpmann.de>wrote:

> Hi Mike,
>
> I can confirm the problem, but I'm not able to track it down.
>
> First of all, I'm quite sure that you cannot share SSL contexts between
> threads. But even if I fix this, I get crashes - usually early during
> SSL_connect.
>
> I'm wondering whether ocaml-ssl initializes openssl correctly for
> multi-threading. In my version of openssl the prototype is
>
> int CRYPTO_THREADID_set_callback(**void (*threadid_func)(CRYPTO_**THREADID
> *));
>
> but in ocaml-ssl the CRYPTO_THREADID pointer is ignored (it assumes void
> here). So, maybe this is the reason. I currently don't have time to follow
> this idea.
>
> If everything fails, there is a way to use Netclient in threaded
> applications so that only one thread is doing the networking stuff, see
> this example:
>
> https://godirepo.camlcity.org/**svn/lib-ocamlnet2/trunk/code/**
> examples/netclient/simple/**http_mt.ml<https://godirepo.camlcity.org/svn/lib-ocamlnet2/trunk/code/examples/netclient/simple/http_mt.ml>
>
> As Netclient is event-driven, the requests are processed in parallel (with
> one exception, though: DNS lookups are synchronous, but this can be worked
> around, as the DNS lookup function is settable in Netclient).
>
> Gerd
>
> Am 27.11.2012 03:54:16 schrieb(en) Mike Lin:
>
>  Hello Gerd, all,
>>
>> I'm trying to find the right incantations to make parallel https requests
>> from multiple threads using Http_client. (I know the library is capable of
>> multiple requests from one thread -- I have other strong reasons to use
>> multithreading.)
>>
>> https://gist.github.com/**4152047 <https://gist.github.com/4152047>
>>
>> This program generally segfaults for me at some random point during the 10
>> requests.  Compiled as in the comment in line 2 (ubuntu quantal,
>> libocamlnet-ocaml-dev 3.5.1, ocaml 3.12.1).
>>
>> Permutations attempted:
>>
>> 1) Change https to http in google URL -- works as expected
>> 2) Serialize requests by uncommenting line 35 -- works as expected
>> 3) Move invocations of Ssl.init, Ssl.create_context,
>> HTTPS.https_transport_channel_**type in and out of fresh_pipeline (which
>> runs
>> in the worker threads) -- no help
>>
>> Any suggestions? Thanks!
>>
>> Mike Lin
>>
>>
>
>
> --
> ------------------------------**------------------------------
> Gerd Stolpmann, Darmstadt, Germany    gerd@gerd-stolpmann.de
> Creator of GODI and camlcity.org.
> Contact details:        http://www.camlcity.org/**contact.html<http://www.camlcity.org/contact.html>
> Company homepage:       http://www.gerd-stolpmann.de
> ------------------------------**------------------------------

[-- Attachment #2: Type: text/html, Size: 4427 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Multithreaded https requests in ocamlnet netclient
  2012-11-28  1:43   ` [Caml-list] " Mike Lin
@ 2013-09-26  8:34     ` Török Edwin
  0 siblings, 0 replies; 4+ messages in thread
From: Török Edwin @ 2013-09-26  8:34 UTC (permalink / raw)
  To: ocamlnet-devel; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 2118 bytes --]

On 11/28/2012 03:43 AM, Mike Lin wrote:
> Thanks, Gerd!
> 
> FWIW I could not reproduce the crash by using ocaml-ssl's blocking operations directly.
> 
> https://gist.github.com/4152047#file_ssl_threads.ml
> 
> This works fine- so, perhaps something nasty arises from using nonblocking I/O on ssl sockets from multiple threads. I'm sure if there is any other critical difference with how netclient/equeue-ssl and my example use ocaml-ssl.
> 
> I also don't have time to pursue this much further, so I will try to put all of my http operations on one thread as your example suggests.

I was debugging a similar bug, and found this old thread with a testcase.
I figured a way to fix it, see the patch below (it didn't acquire the OCaml master lock before raising an 
exception, causing Ocaml code to be executed in parallel with other OCaml code ... leading to all sorts of nasty situations).

Debugging thread-related bugs is hard, especially that none of the usual tools help here.
I modified st_posix.h a bit by adding an m->owner field and checking it against pthread_self() to make sure
a thread attempts to release only a lock it acquired itself, but there is more that could be done
(check in raise_with_arg/etc. that we do hold the master lock, check after returning from each C call that
we do hold the lock, same for C callbacks, etc.). 

Would it be possible to do add checks like this with '-runtime-variant d', i.e. can the thread implementation be changed to a "checking" one in that case?

The patch:
Index: src/equeue-ssl/ssl_exts_stubs.c
===================================================================
--- src/equeue-ssl/ssl_exts_stubs.c     (revision 1913)
+++ src/equeue-ssl/ssl_exts_stubs.c     (working copy)
@@ -27,6 +27,7 @@
   caml_enter_blocking_section();
   ret = SSL_shutdown(ssl);                                    
   if (ret == -1) {                                            
+      caml_leave_blocking_section();                          
       raise_with_arg(*caml_named_value("ssl_exn_shutdown_error"), 
                     Val_int(SSL_get_error(ssl, ret)));        
   };   


[-- Attachment #2: netclient_https_threads.ml --]
[-- Type: text/x-ocaml, Size: 1262 bytes --]

(*
ocamlfind ocamlopt -o netclient_https_threads -thread -linkpkg -package threads,netclient,ssl,equeue-ssl netclient_https_threads.ml

http://docs.camlcity.org/docs/godipkg/3.12/godi-ocamlnet/doc/godi-ocamlnet/html/Https_client.html
*)

open Printf
module HTTP = Http_client
module HTTPS = Https_client
;;

let mutex = Mutex.create ()
let compact () =
  Mutex.lock mutex;
  Gc.compact ();
  Mutex.unlock mutex;;

let () = Ssl.init ~thread_safe:true ();;

let fresh_pipeline () =
  let pipeline = new HTTP.pipeline in
  let ssl_ctx = Ssl.create_context Ssl.TLSv1 Ssl.Client_context in
  let tct = HTTPS.https_transport_channel_type ssl_ctx in
  pipeline#configure_transport HTTP.https_cb_id tct;
  pipeline
;;

let f () =
  begin try
    Mutex.lock mutex;
    let pipeline = fresh_pipeline () in
    let call = new HTTP.get "https://www.google.com/" in
    pipeline#add call;
    pipeline#run ();
    Mutex.unlock mutex;
    printf "ok\n%!";
    flush stdout;
  with e ->
    Printf.eprintf "Error: %s\n%!" (Printexc.to_string e)
  end;
;;

let threads = Queue.create ();;

for i = 1 to 10 do
  Queue.add (Thread.create f ()) threads;
  (*Thread.join (Queue.take threads)*)
done;;

while not (Queue.is_empty threads) do
  Thread.join (Queue.take threads)
done;;

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2013-09-26  8:34 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-11-27  2:54 [Caml-list] Multithreaded https requests in ocamlnet netclient Mike Lin
2012-11-27 13:03 ` [Caml-list] AW: " Gerd Stolpmann
2012-11-28  1:43   ` [Caml-list] " Mike Lin
2013-09-26  8:34     ` [Caml-list] " Török Edwin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).