perlapp problems on Windows w/ SSL (libeay32.dll / ssleay32.dll)

Posted by Akira Kawasaki on 2009-02-05 11:03
Forums: PDK discussion | OS: Windows

PROBLEM SUMMARY:
Windows PerlApp crashes because it loads the wrong version of a bound dll (SSL dll's in my case). Root cause is that the app runs from the location of the exe rather than the pdk temporary directory where the bound dlls are extracted.

DETAILS:
The problem occurred in Windows PerlApp projects using SSL (using modules Crypt::SSLeay or NET::SSLeay). To make the final executable complete, the following DLL's had to be bound explicitly to the project: libeay32.dll and ssleay32.dll).

On some end user systems, the applications would simply crash with no error message and on others they showed an error like "The ordinal 2821 could not be located in the dynamic link library LIBEAY32.dll."

Using a free program called CProcess, I determined that if the Windows system32 directory contained a copy of the dlls then the system32 dll was used. Normally, the system32 dll version was not compatible my application.

This behavior is explained by how perlapp generated executables run and how Windows locates dlls. Your perlapp exe runs from wherever its exe file is located, but the bound dlls are extracted into a pdk temp directory. Windows first searches the directory where the exe is and does not find the bound dlls. The 2nd place Windows searches for the dlls is in the shared system32 directory, and thus the problem. (This MSDN article describes the Windows search order for dlls http://msdn.microsoft.com/en-us/library/ms682586.aspx.)

POSSIBLE SOLUTIONS:
I never did find a great way to resolve this issue but tried a few different workarounds:

(1) package the application with an installer that puts the executable into a diretory along with the dlls (not ideal since many users did not have rights to install things on the PC they were using),

(2) have the application extract the dlls into the directory where the exe is located as soon as the program starts and clean up the dlls on exit (ugly since there's no telling where the user is running my application from--often their desktop),

(3) have the application execute another instance of itself from a directory where the bound dlls were extracted.

I ended up choosing a variation of 3, but this solution works in a way I did not anticipate. The application creates a temporary directory and copies itself and the dlls into the temporary directory and runs the temporary copy of the exe using the "system" command. Unexpectedly, the child process behaves as if the temporary exe is in the parent's temporary pdk directory and actually loads the bound dlls extracted by the parent. Theoretically I'd probably be safe having the parent process re-run its own executable. The child process should pick up the parent's extracted bound dlls--skipping the whole temporary exe copy step.

I am using PDK versions 7.0 or older. Perhaps AcitveState has addressed this in later versions. If you happen to know of a silly switch I've missed in the perlapp config please let me know, but I tried every possible combination of options I could think of.

Good luck.

jfisher | Wed, 2009-07-01 09:36

I am also getting the libeay32.dll issue.

Funny thing though; when I compile the program, it works fine on my XP Pro machines, it works fine on most Vista machine, and it works on some XP Home machines. The common thread seems to be is it works on "newer hardware".

I also included libeay32.dll and ssleay32.dll as bound to the executable. I copied those two files to the same directory as the executable at runtime. I still get teh "Ordinal 2580 could not be found in libeay32.dll" message.

My code uses use Mail::POP3Client though Net::SSLeay to connect and download messages from GMail, which uses SSL.

My last thought is that this is an "old network driver" issue.

Any ideas what I am missing, or doing wrong?