Add App > Get with File: full app backup zip from the device
Reads app.sab and kits.scode over Sox file transfer, decodes app.sab to app.sax (byte-identical to sedonac), and on Orion/Rion also fetches the images and fonts the app names, with their sources from Sedona home's banks. Offers to save the app on the device first when it is dirty, and asks where to save with <Sedona home>/store/apps and app-<device>-<app>-<timestamp>.zip filled in. DASP trace lines are now printed by their own thread: printing from the network threads to an unread stdout pipe blocked the receiver and made file transfers time out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -98,7 +98,56 @@ def _trace(direction, msg, datagram=None):
|
||||
hexdump = ""
|
||||
if datagram:
|
||||
hexdump = " [" + datagram.hex(" ") + "]"
|
||||
print(f"[DASP] {ts} {direction} {name}{seq}{ack} payload={plen}{hexdump}")
|
||||
_trace_out(f"[DASP] {ts} {direction} {name}{seq}{ack} payload={plen}{hexdump}")
|
||||
|
||||
|
||||
# Trace lines are printed by a thread of their own. The send and receive threads must
|
||||
# never wait on the console: when stdout is a pipe nobody reads, print blocks once the
|
||||
# pipe fills, and a file transfer's burst of chunks filled it in seconds -- the
|
||||
# receiver stopped and every request timed out. A full queue drops lines instead.
|
||||
_trace_queue = queue.Queue(maxsize=5000)
|
||||
_trace_thread = None
|
||||
_trace_dropped = 0
|
||||
|
||||
|
||||
def _trace_out(line):
|
||||
global _trace_thread, _trace_dropped
|
||||
if _trace_thread is None:
|
||||
_trace_thread = threading.Thread(target=_trace_writer, name="DaspTrace", daemon=True)
|
||||
_trace_thread.start()
|
||||
try:
|
||||
_trace_queue.put_nowait(line)
|
||||
except queue.Full:
|
||||
_trace_dropped += 1
|
||||
|
||||
|
||||
def _trace_writer():
|
||||
global _trace_dropped
|
||||
while True:
|
||||
line = _trace_queue.get()
|
||||
if _trace_dropped:
|
||||
dropped, _trace_dropped = _trace_dropped, 0
|
||||
line = f"[DASP] ... {dropped} trace lines dropped (console not keeping up)\n{line}"
|
||||
_write_stdout(line + "\n")
|
||||
|
||||
|
||||
def _write_stdout(text):
|
||||
"""Writes to the process's stdout handle directly, past Python's buffered writer.
|
||||
|
||||
The buffered writer has a lock, and a daemon thread holding it while the
|
||||
interpreter shuts down aborts the process ("could not acquire lock for stdout").
|
||||
"""
|
||||
import sys
|
||||
stream = sys.__stdout__
|
||||
if stream is None: # pythonw: no console to write to
|
||||
return
|
||||
try:
|
||||
fd = stream.fileno()
|
||||
data = text.encode(stream.encoding or "utf-8", errors="replace")
|
||||
while data:
|
||||
data = data[os.write(fd, data):]
|
||||
except (OSError, ValueError):
|
||||
pass
|
||||
|
||||
|
||||
_ERROR_HINTS = {
|
||||
|
||||
Reference in New Issue
Block a user