Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Indy 10 + OpenSSL: error:140A90F1:lib(20):func(169):reason(241)
I can confirm now, that for sure the problem comes from openSSL dll library sharing between the host exe app and dll plugin library.
Main problem comes from Windows dll handlig - if you use one and the same dll library in the host app and in the plugin dll libray, Windows does not load fresh copy of dll library, it uses the same. allready loaded into host app, described here:

In this case, this cause call of "LoadOpenSSLLibrary" twice, for one and the same OpenSLL library instance.
It mismatching call of "CRYPTO_set_locking_callback", and finally - it will call "CRYPTO_set_locking_callback(nil);" into dll plugin ibrary, which cause to fail an Openssl in main .exe application.

So - I did a following:

- I create a global DLL handle objects in IdSSLOpenSSLHeaders.pas unit:

  hGlobalIdSSL    : TIdLibHandle = IdNilHandle;
  hGlobalIdCrypto : TIdLibHandle = IdNilHandle;

and global critical section
csGlobalIDSSL  : TIdCriticalSection;

and thread-safe methods for get/set values:

function GlobalIdSSL : TIdLibHandle;
function GlobalIdCrypto : TIdLibHandle;
procedure SetGlobalIdSSL ( fGlobalIdSSL : TIdLibHandle );
procedure SetGlobalIdCrypto ( fGlobalIdCrypto : TIdLibHandle );

and move then 

  hIdSSL    : TIdLibHandle = IdNilHandle;
  hIdCrypto : TIdLibHandle = IdNilHandle;

from "Implementaion" to "Interface" section;

and I modify a "load" method:

  if hIdCrypto = IdNilHandle then begin

    // Zdravko Gabrovski - Global OpenSSL handler implementation
    if GlobalIdCrypto <> IdNilHandle then
      hIdCrypto := GlobalIdCrypto
    else begin
      hIdCrypto := LoadSSLCryptoLibrary;

    if hIdCrypto = IdNilHandle then begin
      FFailedLoadList.Add(IndyFormat(RSOSSFailedToLoad, [GIdOpenSSLPath + SSLCLIB_DLL_name {$IFDEF UNIX}+ LIBEXT{$ENDIF}]));

  if hIdSSL = IdNilHandle then begin

    // Zdravko Gabrovski - Global OpenSSL handler implementation
    if GlobalIdSSL <> IdNilHandle then
      hIdSSL := GlobalIdSSL
      hIdSSL := LoadSSLLibrary;

    if hIdSSL = IdNilHandle then begin
      FFailedLoadList.Add(IndyFormat(RSOSSFailedToLoad, [GIdOpenSSLPath + SSL_DLL_name {$IFDEF UNIX}+ LIBEXT{$ENDIF}]));

- modification of the both functions LoadOpenSSLLibrary and UnLoadOpenSSLLibrary in the  IdSSLOpenSSL.pas - now they will check if the new  "GlobalIdSSL " and "GlobalIdCrypto " object are assigned, they take the hadle from the variables instad of to load them from a Windows load library, and in that case - Do not call 
CRYPTO_set_locking_callback method and all other funcions for init.

Now everything works fine. A pass a handles from the host .exe to the plugin dll library:

In my Host .exe code (delhi 10.3 rio):

  Params.Values['hIdSSL']:=   hIdSSL.ToString; // from IdSSLOpenSSLHeaders
  Params.Values['hIdCrypto']:=   hIdCrypto.ToString; // from IdSSLOpenSSLHeaders

In my plugin dll library (Lazarus 2.1 fpc 3.3.1)

    lhIdSSL :=  StrToUInt64Def( Tl.Values['hIdSSL'], 0 );  // Handler comes from host app
    lhIdCrypto :=  StrToUInt64Def( Tl.Values['hIdCrypto'], 0 );
    if ( lhIdSSL <> IdNilHandle ) and ( lhIdCrypto <> IdNilHandle ) then begin
      SetGlobalIdSSL( lhIdSSL );
      SetGlobalIdCrypto( lhIdCrypto );


That's all.

I try to attach changes here, but I can not. It will tell me "File type is not allowed".

I try to create a branch and open a new pull request, but it is not possible, as described here:

My Github account is ZGabrovski.

Messages In This Thread
RE: Indy 10 + OpenSSL: error:140A90F1:lib(20):func(169):reason(241) - by - 09-04-2020, 09:26 AM

Forum Jump:

Users browsing this thread: 1 Guest(s)