fix: replace Popen readline loop with subprocess.run for Windows pipe reliability; add close_hw before quit in TCL; revert console=True
This commit is contained in:
@@ -277,6 +277,8 @@ open_hw_target
|
|||||||
current_hw_device [lindex [get_hw_devices] 0]
|
current_hw_device [lindex [get_hw_devices] 0]
|
||||||
program_hw_device -file "{bit_path}"
|
program_hw_device -file "{bit_path}"
|
||||||
refresh_hw_device
|
refresh_hw_device
|
||||||
|
close_hw
|
||||||
|
disconnect_hw_server
|
||||||
quit
|
quit
|
||||||
"""
|
"""
|
||||||
tcl_path = bit_path.parent / "temp_program.tcl"
|
tcl_path = bit_path.parent / "temp_program.tcl"
|
||||||
|
|||||||
+18
-21
@@ -125,7 +125,7 @@ def check_zynq_jtag(
|
|||||||
if callback:
|
if callback:
|
||||||
callback("progress", "Scanning JTAG chain...")
|
callback("progress", "Scanning JTAG chain...")
|
||||||
|
|
||||||
# ── 3. Run Vivado TCL (stream output to callback) ──────────
|
# ── 3. Run Vivado TCL ──────────────────────────────────────
|
||||||
tcl = _build_jtag_query_tcl()
|
tcl = _build_jtag_query_tcl()
|
||||||
python_timeout = config.step_timeouts.get("check_env", 120)
|
python_timeout = config.step_timeouts.get("check_env", 120)
|
||||||
|
|
||||||
@@ -141,31 +141,27 @@ def check_zynq_jtag(
|
|||||||
|
|
||||||
output_lines: list[str] = []
|
output_lines: list[str] = []
|
||||||
try:
|
try:
|
||||||
proc = subprocess.Popen(
|
cmd = build_tool_command(vivado_path, *vivado_args)
|
||||||
build_tool_command(vivado_path, *vivado_args),
|
# Use run() with communicate() under the hood — reliably
|
||||||
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
|
# drains pipes on Windows even when .bat wrappers are involved
|
||||||
|
result = subprocess.run(
|
||||||
|
cmd,
|
||||||
|
capture_output=True,
|
||||||
text=True,
|
text=True,
|
||||||
|
timeout=python_timeout,
|
||||||
)
|
)
|
||||||
# Read line by line so user sees real-time progress
|
output = result.stdout + result.stderr
|
||||||
deadline = time.monotonic() + python_timeout
|
for line in output.splitlines():
|
||||||
while True:
|
stripped = line.strip()
|
||||||
line = proc.stdout.readline() if proc.stdout else ""
|
if stripped:
|
||||||
if not line:
|
output_lines.append(stripped)
|
||||||
if proc.poll() is not None:
|
if callback:
|
||||||
break
|
callback("progress", stripped)
|
||||||
if time.monotonic() > deadline:
|
except subprocess.TimeoutExpired:
|
||||||
proc.kill()
|
|
||||||
proc.wait()
|
|
||||||
return _fail(
|
return _fail(
|
||||||
f"JTAG scan timed out after {python_timeout}s",
|
f"JTAG scan timed out after {python_timeout}s",
|
||||||
hw_server_url,
|
hw_server_url,
|
||||||
)
|
)
|
||||||
time.sleep(0.1)
|
|
||||||
continue
|
|
||||||
line = line.rstrip("\n\r")
|
|
||||||
output_lines.append(line)
|
|
||||||
if callback and line.strip():
|
|
||||||
callback("progress", line)
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
return _fail(f"Failed to run Vivado: {e}", hw_server_url)
|
return _fail(f"Failed to run Vivado: {e}", hw_server_url)
|
||||||
finally:
|
finally:
|
||||||
@@ -173,7 +169,6 @@ def check_zynq_jtag(
|
|||||||
Path(tcl).unlink(missing_ok=True)
|
Path(tcl).unlink(missing_ok=True)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
# Clean up Vivado temp files we redirected
|
|
||||||
for f in ("vivado_jtag.jou", "vivado_jtag.log"):
|
for f in ("vivado_jtag.jou", "vivado_jtag.log"):
|
||||||
try:
|
try:
|
||||||
(Path(tmp) / f).unlink(missing_ok=True)
|
(Path(tmp) / f).unlink(missing_ok=True)
|
||||||
@@ -267,6 +262,8 @@ foreach dev [get_hw_devices] {
|
|||||||
puts "DEVICE:$name IDCODE:$idcode"
|
puts "DEVICE:$name IDCODE:$idcode"
|
||||||
}
|
}
|
||||||
puts "===JTAG_END==="
|
puts "===JTAG_END==="
|
||||||
|
close_hw
|
||||||
|
disconnect_hw_server
|
||||||
quit
|
quit
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
|||||||
Reference in New Issue
Block a user