Address further Codex findings on the image-workflows PR
- Persist the actual output image size in the gallery recipe instead of the request sliders: Transform/Inpaint/Edit derive the size from the uploaded image, Extend grows the canvas, and Upscale resizes it, so the sliders recorded (and later restored) the wrong dimensions for those workflows. - Reject a remote '*-GGUF' repo loaded as a full pipeline (no single-file name) in validate_load_request, so the unloadable pick fails before chat is evicted rather than deep in from_pretrained. - Only publish an image-conditioned from_pipe wrapper to the shared aux cache when the load is still current: from_pipe runs under the generate lock but not the state lock, so an unload racing its construction could otherwise cache a wrapper over torn-down modules that a later load would reuse. - Verify the Windows CUDA runtime archive checksum before extracting it, like the main sd-cli archive, so a corrupt or tampered runtime is rejected rather than extracted next to the binary.
This commit is contained in:
parent
8772f81e75
commit
691bad30c4
4 changed files with 34 additions and 3 deletions
|
|
@ -488,6 +488,16 @@ class DiffusionBackend:
|
|||
)
|
||||
elif path_shaped:
|
||||
raise FileNotFoundError(f"Local model path does not exist: {repo_id}")
|
||||
elif repo_id.upper().endswith("-GGUF"):
|
||||
# A remote "*-GGUF" id is a single-file GGUF repo, not a full diffusers
|
||||
# pipeline: loading it as a pipeline passes the trusted-repo check, evicts
|
||||
# chat, then fails in the background when from_pretrained finds no
|
||||
# model_index.json. Reject the certain case here (no network round-trip)
|
||||
# so the bad pick fails before the GPU handoff, as the route expects.
|
||||
raise ValueError(
|
||||
f"'{repo_id}' is a single-file GGUF repo; load it with model_kind 'gguf' "
|
||||
f"and a .gguf filename, not as a full pipeline."
|
||||
)
|
||||
return fam
|
||||
|
||||
# ── Background load + progress ─────────────────────────────────────────
|
||||
|
|
@ -1348,7 +1358,14 @@ class DiffusionBackend:
|
|||
# reuse the resident modules AT THEIR LOADED dtype, which is the whole point of
|
||||
# from_pipe (component reuse, no reload, no extra VRAM).
|
||||
pipe = getattr(diffusers, class_name).from_pipe(state.pipe, torch_dtype = None)
|
||||
self._aux_pipes[class_name] = pipe
|
||||
# Only publish to the shared aux cache if THIS load is still current. from_pipe runs
|
||||
# under _generate_lock but NOT _lock, so an unload()/superseding load can clear
|
||||
# _aux_pipes and null _state while it builds; caching unconditionally would re-insert
|
||||
# a wrapper over now-stale modules that a later same-workflow load would reuse (or
|
||||
# keep the old VRAM pinned). This generation still uses the returned pipe.
|
||||
with self._lock:
|
||||
if self._state is state:
|
||||
self._aux_pipes[class_name] = pipe
|
||||
return pipe
|
||||
|
||||
@staticmethod
|
||||
|
|
|
|||
|
|
@ -11199,8 +11199,13 @@ async def generate_diffusion_image(
|
|||
{
|
||||
"prompt": request.prompt,
|
||||
"negative_prompt": request.negative_prompt,
|
||||
"width": request.width,
|
||||
"height": request.height,
|
||||
# Persist the ACTUAL output size, not the request sliders: Transform/
|
||||
# Inpaint/Edit derive it from the uploaded image, Extend grows the
|
||||
# canvas, and Upscale resizes it, so request.width/height would record
|
||||
# (and later restore) the wrong dimensions for those workflows. For
|
||||
# plain txt2img the image size equals the sliders anyway.
|
||||
"width": getattr(image, "width", None) or request.width,
|
||||
"height": getattr(image, "height", None) or request.height,
|
||||
"steps": request.steps,
|
||||
"guidance": request.guidance,
|
||||
"seed": seed,
|
||||
|
|
|
|||
|
|
@ -1461,6 +1461,11 @@ def test_validate_load_request(tmp_path):
|
|||
backend.validate_load_request(
|
||||
"unsloth/Qwen-Image-2512-FP8", gguf_filename = "q.gguf", model_kind = "single_file"
|
||||
)
|
||||
# A remote "*-GGUF" repo loaded as a full pipeline (no single-file name) is a single-file
|
||||
# GGUF repo, so from_pretrained would find no pipeline manifest and fail after chat is
|
||||
# already evicted; reject it here before the GPU handoff.
|
||||
with pytest.raises(ValueError, match = "GGUF"):
|
||||
backend.validate_load_request("unsloth/Z-Image-Turbo-GGUF", model_kind = "pipeline")
|
||||
# A local path with a missing child fails here (before any GPU/network work).
|
||||
with pytest.raises(FileNotFoundError):
|
||||
backend.validate_load_request(
|
||||
|
|
|
|||
|
|
@ -262,6 +262,10 @@ def _maybe_fetch_windows_cudart(release: dict, chosen: str, target: Path) -> Non
|
|||
print(f"downloading CUDA runtime {cudart['name']} ...", flush = True)
|
||||
try:
|
||||
_download(cudart["browser_download_url"], dest)
|
||||
# Verify integrity BEFORE extracting, like the main sd-cli archive: these DLLs are
|
||||
# loaded into sd-cli.exe at runtime, so a corrupt/tampered runtime archive must be
|
||||
# rejected rather than extracted next to the binary.
|
||||
_verify_sha256(dest, cudart.get("digest"))
|
||||
with zipfile.ZipFile(dest) as zf:
|
||||
_safe_extractall(zf, target)
|
||||
finally:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue