Python subprocess.Popen() - subprocess causes sockets to remain open - python

I have a Python2.7 script that does some parallelism magic and finally enters Flask gui_loop. At some point a thread creates a background process with subprocess.Popen. This works.
When my script exits and if the subprocess is still running, I can't run my script again, as flask gui_loop fails with:
socket.error: [Errno 98] Address already in use
With netstat -peanut I can see the ownership of the socket transfers to the child process when the python script exits. This is how it looks when both python script and subprocess are running:
root#test:/tmp# netstat -peanut | grep 5000
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 1000 840210 21458/python
After terminating the Python script, socket does not close but its ownership is passed to the child process:
root#test:~/PycharmProjects/foo/gui# netstat -peanut | grep 5000
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 1000 763103 19559/my-subprocess
Is there any way around this? The subprocess (written in C) is not doing anything on that socket and doesn't need it. Can I somehow create a subprocess without passing the gui loop socket resource to it?
I can of course terminate the process but this is not ideal as the purpose of this is to build a simple gui around some calculations and not lose the progress if the gui script happens to exit. I would have a mechanism to reattach connection to the subprocess if I just could get the gui script up and running again.
R

You should use close_fds=True when creating the subproces, which will cause all file descriptors (and therfore open sockets) to be closed in the child process (except for stdin/stdout/stderr).
In newer versions (python 3.2+) close_fds already defaults to True, as in most cases you don't want to inherit all open file descriptors in a child process, but in python2.7 you still need to specify it explicitly.

You could try using the with statement. Some documentation here:
http://preshing.com/20110920/the-python-with-statement-by-example/
https://www.python.org/dev/peps/pep-0343/
This does open/close cleanup for you.

Related

How to get a socket FD according to the port occupied in Python?

In my program, A serve-forever daemon is restarted in a subprocess.
The program itself is a web service, using port 5000 by default.
I don't know the detail of the start script of that daemon, but it seems to inherit the socket listening on port 5000.
So if I were to restart my program, I'll find that the port is already occupied by the daemon process.
Now I am considering to fine tune the subprocess function to close the inherited socket FD, but I don't know how to get the FD in the first place.
It seems like a permission issue. The subprocess is probably running as an other user and therefore you will not have access to the process. Use sudo ps xauw |grep [processname] to figure as under what user the daemon process is running.
There is close_fds parameter (subprocess.Popen) that is safe to set to True on Unix (it is default on Python 3). Though you shouldn't need it: a proper daemon should close all open file descriptors itself before forking.
Unrelated: if you want your program to be able to restart during the TIME_WAIT period; set SO_REUSEADDR socket option.

Python in Raspberry socket.error: [Errno 98] Address already in use when creating socket [duplicate]

In my Python socket program, I sometimes need to interrupt it with Ctrl-C. When I do this, it does close the connection using socket.close().
However, when I try to reopen it I have to wait what seems like a minute before I can connect again. How does one correctly close a socket? Or is this intended?
Yes, it is intended. Here you can read detailed explanation. It is possible to override this behavior by setting SO_REUSEADDR option on a socket. For example:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
$ ps -fA | grep python
501 81211 12368 0 10:11PM ttys000 0:03.12
python -m SimpleHTTPServer
$ kill 81211
This happens because you trying to run service at the same port and there is an already running application.
it can happen because your service is not stopped in the process stack. you just have to kill those processes.
There is no need to install anything here is the one line command to kill all running python processes.
for Linux based OS:
Bash:
kill -9 $(ps -A | grep python | awk '{print $1}')
Fish:
kill -9 (ps -A | grep python | awk '{print $1}')
If you use a TCPServer, UDPServer or their subclasses in the socketserver module, you can set this class variable (before instantiating a server):
socketserver.TCPServer.allow_reuse_address = True
(via SocketServer.ThreadingTCPServer - Cannot bind to address after program restart )
This causes the init (constructor) to:
if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Nothing worked for me except running a subprocess with this command, before calling HTTPServer(('', 443), myHandler):
kill -9 $(lsof -ti tcp:443)
Of course this is only for linux-like OS!
A simple solution that worked for me is to close the Terminal and restart it.
For Linux,
ps aux | grep python
This will show you the error. The process number (eg.35225) containing your python file is the error.
Now,
sudo kill -9 35225
This will kill the error process and your problem will be solved.
First of all find the python process ID using this command
ps -fA | grep python
You will get a pid number by naming of your python process on second column
Then kill the process using this command
kill -9 pid
run the command
fuser -k (port_number_you_are _trying_to_access)/TCP
example for flask: fuser -k 5000/tcp
Also, remember this error arises when you interput by ctrl+z. so to terminate use ctrl+c
I faced similar error at odoo server and resolved that with these simple following steps:
Paste following code in terminal
ps -fA | grep python
You will get a pid number. Now copy the pid number from second column of terminal output.
Then write as below
kill -9 pid
The terminal will restart and then the command
flask run
Will work fine!
Thank you
Do nothing just wait for a couple of minutes and it will get resolved. It happens due to the slow termination of some processes, and that's why it's not even showing in the running processes list.
I had the same problem (Err98 Address already in use) on a Raspberry Pi running python for a EV charging manager for a Tesla Wall Connector. The software had previously been fine but it stopped interrogating the solar inverter one day and I spent days thinking it was something I'd done in python. Turns out the root cause was the Wifi modem assigning a new dynamic IP to the solar inverter as as result of introducing a new smart TV into my home. I changed the python code to reflect the new IP address that I found from the wifi modem and bingo, the issue was fixed.
Got this error after I ran my code while programming a Pico W via Thonny. At the command line just do a socket.reset() to clear the issue.
>>> socket.reset()
The cleanest way to make the socket immediately reusable is to follow the recommendation to first shutdown the client end (socket) of a connection, and make sure the server's end shuts down last (through exception handling if needed).
This might well mean that the server end runs forever.
This is not a problem if that "forever" loop pauses execution, e.g. read from socket.
How you "break" that "forever" loop is up to you as server admin, as long as there are no clients (apart from obvious system level exceptions)
I tried the following code to settle the issue:
sudo lsof -t -i tcp:8000 | xargs kill -9
sudo pkill -9 python
try this command

Spawn a subprocess in foreground, even after python exits

Assume there exists a python script resolve_ip.py which magically returns the string IP of a machine we care about.
I'm interested in learning how to achieve the python equivalent of the following bash command:
user#host:~$ ssh $(./resolve_ip.py)
In this bash example, after the python script runs, it is replaced or rather substituted with its return value which is, in turn, provided as a input to the program ssh. The result is, the python program terminates and the user interacts with ssh initialization.
The problem is, this solution requires the use of either 2 scripts (a bash script to run ssh, combined with the python script to return the arguments) or alternatively human intervention to type the bash command directly as formatted above.
Question:
Is there a way, only using python, to start/fork an interactive service (like ssh), by using subprocess or some comparable module, and have this forked child process remain alive in the foreground, even after its parent (python) has sys.exit()'d?
Considerations:
In this case, the point of this question is not to script the submission of ssh credentials to ssh from within Python. It is how to spawn a subprocess which continues to run foregrounded after its parent/spawner terminates.
EDIT:
The following resources are related:
Run a program from python, and have it continue to run after the script is killed
how to spawn new independent process in python
Indefinite daemonized process spawning in Python
Python spawn off a child subprocess, detach, and exit
I think you want to "exec". Like this:
import resolve_ip
import os
host = resolve_ip.get_host_to_use() # you figure this part out
os.execlp('ssh', 'ssh', host)
That will replace the Python interpreter process image with the ssh process image, and keep running. So you will end up as if you had run ssh instead of Python, and the interpreter will no longer execute at all.

How to make sure All spawned processes die when I Kill a Python Paramiko script?

How does one ensure when I spawn a process on a remote machine using Python Paramiko, that the process will die when the connection does?
Specifically, the issue I'm having is I'll run wget or some other command using Paramiko, and it will hang. Unfortunately, when I kill the python script process directly, The process on the remote machine does not die. It just keeps running and I have another hanging process.
I have to kill the process directly because I'm trying to link it with a tool which can only kill processes directly.
I've heard that this can be done in SSH by making SSH a "Control Terminal". Is there anything in Paramiko that can do this, or just kill any processes on a remote machine after it spawned?
Thanks!

Python [Errno 98] Address already in use

In my Python socket program, I sometimes need to interrupt it with Ctrl-C. When I do this, it does close the connection using socket.close().
However, when I try to reopen it I have to wait what seems like a minute before I can connect again. How does one correctly close a socket? Or is this intended?
Yes, it is intended. Here you can read detailed explanation. It is possible to override this behavior by setting SO_REUSEADDR option on a socket. For example:
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
$ ps -fA | grep python
501 81211 12368 0 10:11PM ttys000 0:03.12
python -m SimpleHTTPServer
$ kill 81211
This happens because you trying to run service at the same port and there is an already running application.
it can happen because your service is not stopped in the process stack. you just have to kill those processes.
There is no need to install anything here is the one line command to kill all running python processes.
for Linux based OS:
Bash:
kill -9 $(ps -A | grep python | awk '{print $1}')
Fish:
kill -9 (ps -A | grep python | awk '{print $1}')
If you use a TCPServer, UDPServer or their subclasses in the socketserver module, you can set this class variable (before instantiating a server):
socketserver.TCPServer.allow_reuse_address = True
(via SocketServer.ThreadingTCPServer - Cannot bind to address after program restart )
This causes the init (constructor) to:
if self.allow_reuse_address:
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
Nothing worked for me except running a subprocess with this command, before calling HTTPServer(('', 443), myHandler):
kill -9 $(lsof -ti tcp:443)
Of course this is only for linux-like OS!
A simple solution that worked for me is to close the Terminal and restart it.
For Linux,
ps aux | grep python
This will show you the error. The process number (eg.35225) containing your python file is the error.
Now,
sudo kill -9 35225
This will kill the error process and your problem will be solved.
First of all find the python process ID using this command
ps -fA | grep python
You will get a pid number by naming of your python process on second column
Then kill the process using this command
kill -9 pid
run the command
fuser -k (port_number_you_are _trying_to_access)/TCP
example for flask: fuser -k 5000/tcp
Also, remember this error arises when you interput by ctrl+z. so to terminate use ctrl+c
I faced similar error at odoo server and resolved that with these simple following steps:
Paste following code in terminal
ps -fA | grep python
You will get a pid number. Now copy the pid number from second column of terminal output.
Then write as below
kill -9 pid
The terminal will restart and then the command
flask run
Will work fine!
Thank you
Do nothing just wait for a couple of minutes and it will get resolved. It happens due to the slow termination of some processes, and that's why it's not even showing in the running processes list.
I had the same problem (Err98 Address already in use) on a Raspberry Pi running python for a EV charging manager for a Tesla Wall Connector. The software had previously been fine but it stopped interrogating the solar inverter one day and I spent days thinking it was something I'd done in python. Turns out the root cause was the Wifi modem assigning a new dynamic IP to the solar inverter as as result of introducing a new smart TV into my home. I changed the python code to reflect the new IP address that I found from the wifi modem and bingo, the issue was fixed.
Got this error after I ran my code while programming a Pico W via Thonny. At the command line just do a socket.reset() to clear the issue.
>>> socket.reset()
The cleanest way to make the socket immediately reusable is to follow the recommendation to first shutdown the client end (socket) of a connection, and make sure the server's end shuts down last (through exception handling if needed).
This might well mean that the server end runs forever.
This is not a problem if that "forever" loop pauses execution, e.g. read from socket.
How you "break" that "forever" loop is up to you as server admin, as long as there are no clients (apart from obvious system level exceptions)
I tried the following code to settle the issue:
sudo lsof -t -i tcp:8000 | xargs kill -9
sudo pkill -9 python
try this command

Categories