Original link: http://ponder.work/2022/08/30/close-subprocess-opened-fd/
When we test the code, because we need to restart the service frequently, we often find that the service port is occupied.
Generally, killing the background process is ok, but if the service starts some resident background programs, the port may not be released.
In UNIX-like systems, all open files and ports are abstracted as file descriptors
Since python3.4, file descriptors are non-inheritable by default, that is, child processes will not share file descriptors.
question
Generally, in order to implement a multi-process and multi-threaded webserver, the service port fd must be set to inherit (set_inheritable), so that multiple processes can monitor a port (with SO_REUSEPORT)
The typical scenario is to use flask’s test server, here we write a piece of code to simulate.
1 |
import socket, os |
We can see all the file descriptors of these two processes through lsof -p {pid}
server process, you can see that the fd of the service port is 4
1 |
COMMAND PID FD TYPE DEVICE SIZE/OFF NODE NAME |
The sleep child process also has a file descriptor of fd=4
1 |
COMMAND PID FD TYPE DEVICE SIZE/OFF NODE NAME |
If the sleep process does not exit when the server process exits, the port corresponding to fd=4 is occupied, and the service cannot be started normally.
Solution
Manual cleanup
1 |
import os |
use close_fds
Use the subprocess library instead of os to start subprograms, and close redundant file descriptors with the close_fds parameter
1 |
import subprocess |
refer to
- https://docs.python.org/3/library/os.html#inheritance-of-file-descriptors
- https://docs.python.org/3/library/subprocess.html#subprocess.Popen
- https://stackoverflow.com/questions/2023608/check-what-files-are-open-in-python#answer-25069136
This article is reprinted from: http://ponder.work/2022/08/30/close-subprocess-opened-fd/
This site is for inclusion only, and the copyright belongs to the original author.