Search code examples
pythonmultiprocessingsolarispyinstaller

Trouble freezing (with PyInstaller) python source including multiprocessing module in Solaris


I'm trying to freeze and distribute among my Solaris11 machines the following python code which makes use of multiprocessing module:

import multiprocessing

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = multiprocessing.Process(target=f, args=('fer',))
    p.start()
    p.join()

However, even if the executable works fine under the compiler machine (Solaris11) ...

[root@zgv-wodbuild01 pyinstaller]# testfer/dist/testfer
hello fer
[root@zgv-wodbuild01 pyinstaller]# echo $?
0

...complains about multiprocessing library in any other machine (Solaris11):

root@dest01a # ./testfer.r004 
Traceback (most recent call last):
File "testfer.py", line 1, in <module>
File "/root/pyinstaller/PyInstaller/loader/pyimod03_importers.py", line 389, in load_module
File "multiprocessing/__init__.py", line 84, in <module>
File "/root/pyinstaller/PyInstaller/loader/pyimod03_importers.py", line 546, in load_module
ImportError: ld.so.1: testfer.r004: fatal: relocation error: file /tmp/_MEIlBa4uh/_multiprocessing.so: symbol __xnet_sendmsg: referenced symbol not found
Failed to execute script testfer
root@dest01a # echo $?
255

PyInstaller command has been launched with --onefile flag so every needed library should be included inside final ELF file (multiprocessing too). But I have also tried to include explicitly multiprocessing library by editing hidden-import section in the .spec file.

I have also tried to freeze the source in an older Solaris 10 machine to ensure backwards compatibility. Compiling the PyInstaller bootloaders both with and without special LDFLAGS like -lrt. Using --debug flag. But so far nothing worked nor gave me a clue.

Apparently the binary is properly built for the right architecture and there is no library issues:

root@dest01a # file testfer.r004 
testfer.r004:   ELF 32-bit MSB executable SPARC32PLUS Version 1, V8+ Required, UltraSPARC1 Extensions Required, dynamically linked, stripped

root@dest01a # crle 
Platform:     32-bit MSB SPARC
Default Library Path (ELF):   /lib:/usr/lib  (system default)
Trusted Directories (ELF):    /lib/secure:/usr/lib/secure  (system default)

root@dest01a # ldd -r testfer.r004 
        libdl.so.1 =>    /lib/libdl.so.1
        libm.so.2 =>     /lib/libm.so.2
        libz.so.1 =>     /lib/libz.so.1
        librt.so.1 =>    /lib/librt.so.1
        libc.so.1 =>     /lib/libc.so.1

root@dest01a # ldd -r /lib/libsocket.so.1 
        libnsl.so.1 =>   /lib/libnsl.so.1
        libc.so.1 =>     /lib/libc.so.1
        libmp.so.2 =>    /lib/libmp.so.2
        libmd.so.1 =>    /lib/libmd.so.1
        libsoftcrypto.so.1 =>    /lib/libsoftcrypto.so.1
        libelf.so.1 =>   /lib/libelf.so.1
        libcryptoutil.so.1 =>    /lib/libcryptoutil.so.1
        libz.so.1 =>     /lib/libz.so.1
        libm.so.2 =>     /lib/libm.so.2

So I ran out of ideas. Thanks in advance for any insight.

Update: Thanks to Andrew Henle comments I've been able to make some progress. I have recompiled the PyInstaller bootloaders again but this time establishing LDFLAGS environment variable to LDFLAGS="-lsocket -lrt".

Now it's not complaining about __xnet symbols anymore but symbol get_fips_mode instead. As you can see:

root@lnrep01a # ./testfer.r004 
ld.so.1: testfer.r004: fatal: relocation error: file /lib/libsoftcrypto.so.1: symbol get_fips_mode: referenced symbol not found
Killed

So probably I just need to add some extra flags to compiling process. I will look for them across the internet but if someone knows what is missing, that would be more than welcome.


Solution

  • Turned out it wasn't a gcc bug. After analysing in depth both environments, I realized the /lib/libsoftcrypto.so.1 libraries differs a lot. As a matter of fact, the library in the compiler machine contains get_fips_mode symbol...

    [root@zgv-wodbuild01 pyinstaller]# nm /lib/libsoftcrypto.so.1  | grep -i get_fips_mode
    [3438]  |    623016|       212|FUNC |GLOB |0    |18     |get_fips_mode
    

    ...while the destination machine does not:

    root@dest01a # nm /lib/libsoftcrypto.so.1  | grep -i get_fips_mode
    [3755]  |         0|         0|FUNC |GLOB |0    |UNDEF  |get_fips_mode
    

    After trying another compiler machine with similar library version, compiling the pyinstaller bootloaders with -lsocket ldflag was enough:

    root@dest01a # ./testferv3
    hello fer
    root@dest01a # echo $?
    0