Why is the serial port still open when killing a subprocess? - python-3.x

I have a programming tool for an ESP32 platform and this programming tool should use the esptool and a task to program the ESP32. This is done by a subprocess:
while(True):
Command = "{}".format(os.getcwd()) + os.path.sep + "esptool.py --port {} --after hard_reset flash_id".format(Port)
print("[DEBUG {}] Run command {}".format(Index, Command))
Proc = subprocess.Popen(Command, shell = True, stdout = subprocess.PIPE)
Output = str()
try:
Output = Proc.communicate(timeout = 10)[0].decode("ascii")
except subprocess.TimeoutExpired:
if(args.debug):
print("[DEBUG {}] Process timeout!".format(Index))
Proc.kill()
# Sometimes the application will stuck here. Use a timeout again to prevent it.
try:
Proc.communicate(timeout = 1)
except subprocess.TimeoutExpired:
pass
# Timeout - jump back and try it again
continue
...
The process is started and a timeout occurs:
[DEBUG 0] Run command ...\app\esptool.py --port COM14 --after hard_reset flash_id
[DEBUG 0] Process timeout!
The application should try the programming process again, but I get SerialException from the esptool.py.
serial.serialutil.SerialException: could not open port 'COM14': PermissionError(13, 'Zugriff verweigert', None, 5)
It looks like the process is still alive. But why? How can I fix it? I´m testing the application with Windows 10, but it also should run under Linux. I´m using Python 3.9.5 64-Bit.

Related

How to interact with a subprocess that does not close/complete?

Hi I am trying to write a script that uses Segger's J-Link tool. When the J-Link tool is run it presents a prompt to the user, then commands can issued to it to perform tasks. Here is what I get if I run it from the command prompt:
C:\Program Files (x86)\SEGGER\JLink>jlink
SEGGER J-Link Commander V6.56b (Compiled Dec 6 2019 15:00:15)
DLL version V6.56b, compiled Dec 6 2019 14:58:46
Connecting to J-Link via USB...O.K.
Firmware: Energy Micro EFM32 compiled Apr 20 2016 12:17:23
Hardware version: V1.00
S/N: 440082037
License(s): RDI
VTref=3.297V
Type "connect" to establish a target connection, '?' for help
J-Link>
When I run the following code:
import subprocess
process = subprocess.Popen('C:\\Program Files (x86)\\SEGGER\JLink\\jlink.exe -nonsense', stdout=subprocess.PIPE, universal_newlines=True)
print(process.stdout.read())
I get the following output
SEGGER J-Link Commander V6.56b (Compiled Dec 6 2019 15:00:15)
DLL version V6.56b, compiled Dec 6 2019 14:58:46
Unknown command line option -nonsense.
But if I remove the -nonsense option the process hangs. This make sense as with a nonsense option J-Link exits with an error, in essence closing stdout.
What I want to do in my script is:
Start the J-Link program
Get the initial output from the program (so I can parse it and determine if the script should continue)
Issue commands to J-Link program
Get any responses, parse them and use this in my script
When the script is finished issue qc command which causes J-Link to close.
What am I doing wrong with my subprocess calls that make the process hang, or what I am trying to do will never work and what else can I try?
Edit:
Using a modified version of the answer found here https://stackoverflow.com/a/36477512/9791536
from threading import Thread
def reader(f,buffer):
while True:
line=f.readline()
if line:
buffer.append(line)
else:
break
process = subprocess.Popen("C:\\Program Files (x86)\\SEGGER\\JLink\\jlink.exe -device EFM32GG380F1024 -if SWD -speed 14000 -autoconnect 1", stdout=subprocess.PIPE)
time.sleep(2)
linebuffer=[]
t=Thread(target=reader,args=(process.stdout,linebuffer))
t.daemon=True
t.start()
while True:
if linebuffer:
print(linebuffer.pop(0))
else:
print("nothing here")
time.sleep(1)
I get a stream of "Nothing here" messages. if I replace the command with simple ping that does not return, I get the expected ping results. Seems like Jlink is not playing ball....
process = subprocess.Popen("C:\\windows\system32\ping.exe 127.0.0.1 -t", stdout=subprocess.PIPE)
Edit 2:
In the past I have tried PyLink Module, but didn't work. So tried again now I have more experience with JLink.
Found I need to call set_tif(1) to set the interface to SWD from default of JTAG. So have thrown away subprocess above code.

Program runs with sudo and root, not with systemd

I have an application that ran for months on Stretch and Python 2.7 and 3.5, on a Raspberry Pi Model 3B+, however when I moved it to Buster and Python 3.7 I ran into a very strange problem. The error message I get is "error saving session_id: write() argument 1 must be unicode, not str" from a json.dump save of a list.
(code: json.dump(client.user_data, fout))
If I run the script as sudo, to test for the eventual running as root by systemd, it works fine. When I run it as root through sudo su, it also works fine. When I run it through systemd I get the error. For many hours I have been going in circles trying to zoom in on the problem, but now I'm baffled.
At first I though that the issue was with the unicode changes in Python, so I tried to eliminate that as a source of the problem. I even went as far as to add a function to really make sure I'm dealing with unicode, and not strings. (function utfy_dict)
The list I'm using and trying to save looks like this, with some fields edited for pricacy: (taken from a print(data) output":
{u'sessionId': u'555C703C-607x-bla-bla', u'userInfo': {u'username': u'my_email#gmail.com', u'city': u'my_city', u'isActivated': True, u'firstname': u'Paul', u'lastname': u'mylastname', u'userID': my userId, u'zipcode': u'my Zipcode', u'telephone': u'', u'deviceCount': 0, u'streetAddress': u'my street', u'securityQuestion3': u'NotUsed', u'securityQuestion2': u'NotUsed', u'securityQuestion1': u'NotUsed', u'country': u'NL', u'userLanguage': u'nl-NL', u'tenantID': 5, u'latestEulaAccepted': False}}
The relevant pieces:
try:
# save the session-id so we don't need to re-authenticate every polling cycle
print("save session_id")
# here comes the offending piece: an exception is raised
utfy_dict(client.user_data)
print(client.user_data)
print("\n")
with io.open(session_id, "w", encoding="utf-8") as fout:
json.dump(client.user_data, fout)
except Exception as error:# (IOError, ValueError,TypeError):
write_log("error", "error saving session_id: {}".format(error))
return
def utfy_dict(dic):
'''
https://stackoverflow.com/questions/33699343/convert-every-dictionary-value-to-utf-8-dictionary-comprehension
'''
if isinstance(dic,bytes):
return(dic.encode("utf-8")) # the key is this!
elif isinstance(dic,dict):
for key in dic:
dic[key] = utfy_dict(dic[key])
return(dic)
elif isinstance(dic,list):
new_l = []
for e in dic:
new_l.append(utfy_dict(e))
return(new_l)
else:
return(dic)
Systemd service file:
# This service installs a Python script that monitors the CV temperatures.
[Unit]
Description=Installing the cv_mon monitoring script
Requires=basic.target
After=multi-user.target
[Service]
ExecStart=/usr/bin/python /home/pi/cv_app.py
Restart=always
# wait for 10s before the SIGKILL gets send
TimeoutStopSec=10s
# The number of times the service is restarted within a time period can be set
# If that condition is met, the RPi is rebooted
#
StartLimitBurst=4
StartLimitInterval=180s
# actions can be none|reboot|reboot-force|reboot-immidiate
StartLimitAction=none
[Install]
WantedBy=multi-user.target
The get_evo_data function gets called every three minutes. I would like to reiterate that the code ran fine for more than a year on another platform, and it also runs fine as sudo or root, just not under systemd.
Here is an error report: (note the reference to Python 2.7/json ???)
2019-07-31 00:15:30,095 ERROR JSON decode error reading evo_saved_data
2019-07-31 00:15:30,099 ERROR Got exception: write() argument 1 must be unicode, not str
2019-07-31 00:15:30,102 INFO Traceback (most recent call last):
File "/home/pi/cv_app.py", line 717, in main
get_evo_data()
File "/home/pi/cv_app.py", line 314, in get_evo_data
json.dump(client.user_data, fout)
File "/usr/lib/python2.7/json/__init__.py", line 190, in dump
fp.write(chunk)
TypeError: write() argument 1 must be unicode, not str

Scapy with eventlet raises "Child died unexpectedly. Packets may have not been sent"

I've been doing some work on port scanning. I'm trying to do a SYN scan (send SYN and and cut the cord if I get an SYN-ACK), and the operation worked perfect on single thread.
When trying to run it using eventlet (on a Celery threaded worker), I get the following exception when running it:
Child died unexpectedly. Packets may have not been sent
The following is my code that raises the issue:
def pscan(dest_ip, dest_port):
packet = IP(dst=dest_ip) / TCP(dport=int(dest_port), flags='S')
res = sr1(packet, verbose=False, timeout=1)
if res and res.haslayer(TCP):
if res[TCP].flags == 18: # SYN-ACK flag
return True
return False
Any thoughts?

Failure running Overtone and SuperCollider

I can't get overtone to work with supercollider server, I'm following the getting started guide at https://github.com/overtone/overtone/wiki/Getting-Started, I've got Jack audio server running through qjackctl, then I ran SuperCollider with scsynth -u 8888 which produced the following output:
Found 12 LADSPA plugins
JackDriver: client name is 'SuperCollider'
SC_AudioDriver: sample rate = 48000.000000, driver's block size = 1024
SuperCollider 3 server ready.
Zeroconf: registered service 'SuperCollider'
then in the clojure repl I connect to SC server:
(connect-external-server 8888)
then when I run (definst foo [] (saw 220))
I get the following error:
CompilerException java.util.concurrent.TimeoutException: deref! timeout
error. Dereference took longer than 5000 ms whilst blocking until the
following node has completed loading: #<synth-group[loading]: Inst foo
Container 41>, compiling:(form-init1483192646581877285.clj:131:7)
and scsynth outputs FAILURE IN SERVER /g_new Group 31 not found
also if I try (demo (sin-osc)) I get the error FAILURE IN SERVER /s_new Group 7 not found
although if I run using sclang:
s.boot;
{ SinOsc.ar(440, 0, 0.2) }.play;
it does produce a sound.
I'm running Manjaro Linux using the Linux 4.9.27 real time Manjaro kernel
and an HDA Intel PCH sound card.

Is it possible to connect to Mobile Safari remote debugger protocol using python?

I have an HTML5-based application running on iOS and I want to connect to it using the webkit remote debugger protocol 1 that is now supported in iOS 5 2.
I am trying to track down a problem where my javascript application is hard crashing the browser (SEG_FAULT). I would like to get a trace of the application as it executes so I can see what line(s) or network operations may be leading to the issue. My current idea is to write a python application that will connect to the remote debugger and keep stepping through the code and collecting information to a log file while I interact with the application.
I ran into an initial hurdle though that I can't find any examples or documentation about how to connect to the debugger and communicate or even if it is possible.
Does anyone know if this is possible and if so can you point me at some documentation and/or example code?
Based on the code from also below I created a project on github to test out some of the ideas. You can find it here: abierbaum:/python_webkit-remote_debugger
Yes, if you've got the inspector enabled in your UIWebView by following the instructions, it should be possible to connect to it from Python. I played around with it, and figured out how to send and receive commands using a Web Socket. Here's a script for Python 2.7 using websocket-client
import json
import socket
from websocket import WebSocket
ws = WebSocket()
# if ipv6
ws.io_sock = ws.sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
ws.connect("ws://localhost:9999/devtools/page/1")
counter = 0
def send(method, params):
global counter
counter += 1
# separators is important, you'll get "Message should be in JSON format." otherwise
message = json.dumps({"id": counter, "method": method, "params": params}, separators=(',', ':'))
print "> %s" % (message,)
ws.send(message)
def recv():
result = ws.recv()
print "< %s" % (result,)
send('Runtime.evaluate', {'expression': 'alert("hello from python")'})
recv()
This uses the Runtime.evaluate function to show an alert.
I tried running it against MobileSafari running in the simulator, and it worked fine. I noticed two important things:
the remote server is bound to an IPv6 port, and websocket-client didn't connect without the line to override the socket and set the family. Not sure if it would be the same running on a device or in a UIWebView.
it doesn't like spaces around the separators in the JSON.
Here's what it looks like enabling the inspector in MobileSafari using gdb and running the script:
$ ps x | grep MobileSafari
4968 ?? Z 0:00.00 (MobileSafari)
6234 ?? S 0:00.69 /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk//Applications/MobileSafari.app/MobileSafari
6238 s007 R+ 0:00.00 grep MobileSafari
$ gdb
GNU gdb 6.3.50-20050815 (Apple version gdb-1708) (Thu Nov 3 21:59:02 UTC 2011)
...
(gdb) attach 6234
Attaching to process 6234.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ........................................................................................................................................................ done
0x99798c22 in mach_msg_trap ()
(gdb) p (void *)[WebView _enableRemoteInspector]
$1 = (void *) 0x2ac93ce
(gdb) detach
Detaching from process 6234.
(gdb) quit
$ python debug.py
> {"params":{"expression":"alert(\"hello from python\")"},"id":1,"method":"Runtime.evaluate"}
< {"result":{"result":{"type":"undefined","description":"undefined"}},"id":1}

Resources