Forum > Networking and Web Programming

Using TFPHttpClient on multiple threads

(1/2) > >>

Frogfather:
Hello,

I'm having a play around with TFPHttpClient and TThread in order to get a better understanding of how these components work together. I used https://forum.lazarus.freepascal.org/index.php?topic=40773.0 as a starting point although that post is a few years old and I'm aware that we should use opensslsockets instead.

So, following the post above I have a class TMyHttpRequest:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---type uses  Classes, SysUtils, fphttpclient, opensslsockets;           { TMyHTTPRequest }   TMyHTTPRequest = class(TThread)  private    fApi: String;    fRes: String;  public    procedure Execute; override;  property api: string read fApi write fApi;  property res: string read fRes write fRes;  end; implementation { TMyHTTPRequest } procedure TMyHTTPRequest.Execute;var  Client: TFPHTTPClient;begin  Client := TFPHTTPClient.Create(nil);  writeln(api);  res := Client.Get(api);  writeln(res);  FreeAndNil(Client);end;                           
and the idea is that the main program can create multiple instances of these and they'll go off and do their thing in separate threads.

Inevitably the calling method is a button click on a form:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---procedure TForm1.Button1Click(Sender: TObject);var  MYThread: array[0..2] of TMyHTTPRequest;  i: integer;begin   for i:=1 to 3 do  begin    MYThread[i] := TMyHTTPRequest.Create(True);    MyThread[i].api:='https://jsonplaceholder.typicode.com/posts/'+inttostr(i);    MYThread[i].FreeOnTerminate := True;    MYThread[i].Start;  end;end;     
So, the first thread works as expected - the call is made and data is returned correctly, but the second and third result in an EInOutError 'could not initialize openssl library'.

If I put sleep(1000) in the loop, giving each thread time to complete before starting the next it works fine. So that suggests that it isn't possible to initialize openssl when it's already in use.

So I'm wondering what is the correct way to make multiple https calls on separate threads?

Thanks in anticipation.
John C

Gustavo 'Gus' Carreno:
Hey John C,

I haven't tried your code, but if you pay attention to the thread you mention, the OP mentions that he solved the issue with:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---InitSSLInterface;
Before he instantiates any of the threads.

I don't see that in your code.
Could that be the solution?

Again, I'm sorry if I misspoke, since I haven't tested you code, and I'm basing this reply on the solution that the OP on that post got to.

Hope it helps in any way!!

Cheers,
Gus

Frogfather:
Hi Gus,
Thanks for the quick reply.

I did try InitSSLInterface without success - same error resulted. Forgot to mention that in my first post.

The OP was using the older method without opensslsockets so maybe it worked using that approach. It does seem to be something to do with only one thread being able to be initialize the openssl library at a time but I don't know enough about its inner workings to work out why that is happening.

Gustavo 'Gus' Carreno:
Hey John,


--- Quote from: Frogfather on September 17, 2021, 11:39:18 pm ---Thanks for the quick reply.

--- End quote ---

You're more than welcome!!


--- Quote from: Frogfather on September 17, 2021, 11:39:18 pm ---I did try InitSSLInterface without success - same error resulted. Forgot to mention that in my first post.

--- End quote ---

Humm, I thought that would solve the problem, sorry about that!


--- Quote from: Frogfather on September 17, 2021, 11:39:18 pm ---The OP was using the older method without opensslsockets so maybe it worked using that approach. It does seem to be something to do with only one thread being able to be initialize the openssl library at a time but I don't know enough about its inner workings to work out why that is happening.

--- End quote ---

Well, this exhaust my knowledge on the matter :(
Sorry I can't be of any further assistance :(

But I do feel that it's a bit odd that the SSL library is not thread safe, or for that matter, is thread aware and messes things up or something.
Quite an interesting conundrum, I'll say!!

Cheers,
Gus

Frogfather:
Hi Gus,

From the openssl docs:


--- Quote ---OpenSSL can generally be used safely in multi-threaded applications provided that at least two callback functions are set, the locking_function and threadid_func. Note that OpenSSL is not completely thread-safe, and unfortunately not all global resources have the necessary locks.
--- End quote ---

So it looks like it should be possible - I'll do a bit more investigation and see if I get anywhere.

Navigation

[0] Message Index

[#] Next page

Go to full version