I'm migrating an application from Python 2 to 3. The app involves in a Python script that orchestrates a few instances of a C app. The python script opens a socket for each app and then passes the corresponding file descriptor to the C program. This works with the original version in Python 2.7 but breaks with Python 3.6 or 3.9.
I was able to find one change: the file descriptors apart from stdin, stdout and stderr are not inherited by the child processes by default (more info here)
What I do is the following:
import socket
import os
import subprocess
sock = socket.socket()
sock.bind(('10.80.100.32',0))
sock
# Out[6]: <socket.socket fd=11, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('10.80.100.32', 36737)>
env = os.environ.copy()
env["LD_LIBRARY_PATH"] = env["LD_LIBRARY_PATH"] + ":%s" % os.getcwd()
p = subprocess.Popen(["./app", "--sockfd", "11"], close_fds = False, env=env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p.pid
# Out[10]: 393727
Then I check the corresponding process: either it exists and there is a server waiting for a connection in case of Python 2 or the process is dead in case of Python 3.
I tried to set the file descriptor to be inheritable:
os.get_inheritable(11)
# Out[15]: False
os.set_inheritable(11, True)
However that did not help, the app still crashes.
I also tried to explicitly pass pass_fds = [11] to Popen, that also did not help.
If I run the app and let it create the socket on its own then it works fine including when it is started from the Python script. So at this point I'm fairly certain that the problem has to do with some changes from Python 2 to Python 3.
Are there any other changes that could be having an impact on the observed behavior? What else could I try to make it work?