Repository navigation
Worker: honour or refuse shared-memory order; memory-map big TIFF inputs - #125
Merged
Merged
Conversation
… inputs Shared-memory descriptors: the worker ignored `order`, so an F-order block was read transposed with no error. It now reads C and F (also Appose's C_ORDER/F_ORDER) with the right strides and refuses any other value with unreadable_image. TIFF inputs: an uncompressed, contiguous, single-series TIFF of at least 8 MiB is mapped copy-on-write instead of read. The tool gets the same shape, dtype and values in a plain writable array; writes never reach the file. Every page's offsets are checked (tifffile's series.dataoffset trusts a series' layout from its first pages). Compressed, tiled, multi-series, pyramid, OME, non-native byte order, small and cut-short files are read as before; LC_TIFF_MEMMAP=0 turns it off. Mappings are released before the terminal message. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
guijacquemet
added a commit
that referenced
this pull request
Oct 13, 2026
rc.1, rc.2 and main all reported 0.2.0rc1 with the same features although the code differs. 0.3.0a1 plus shm_order_v1 (shared-memory `order`, PR #125, already implemented) tell them apart. - _version 0.3.0a1; FEATURES + PROTOCOL.md table and feature tests - PROTOCOL.md: retention_prune is in rc.1; runs.build_record/record_json/ done_status arrive in 0.3.0a1; big TIFFs are mapped from 0.3.0a1 (no id) - OPERATIONS.md: pre-release pin rule, tag <-> PEP 440 name rule, rc.2 did not bump, no rc.3, Windows file-lock caveat; install snippets -> alpha.1 - CI compat job: newest tag sorted with versionsort.suffix (final beats its own pre-releases, alpha.1 beats rc.2) - conformance.json version_order, frozen tools_0.3 schema fixture, compat matrix - release sandbox: expected Tools pin is an argument (default: read from the app's post_install hook) instead of a constant - docs/RELEASE_NOTES_0.3.0-alpha.1.md (draft for the GitHub pre-release) Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN Co-authored-by: Claude <noreply@anthropic.com>
guijacquemet
added a commit
that referenced
this pull request
Oct 13, 2026
…test hygiene, CI hardening (#129) * Audit fixes before the alpha: say why a big TIFF was not mapped, ledger, docs, test hygiene - convert._memmap_tiff: a TIFF of 8 MiB or more that is read the plain way logs one warning (file, reason) to the log and the worker's stderr - worker._orphan_exit: a temp folder that cannot be removed is logged - ledger rows for #124 and #125, real PR numbers instead of "this PR", pending section replaced by a note - docs: tag install URLs, OPERATIONS contradictions, HOST_FEATURES rows, Playground rule, features rule exception - tests: new tests and sabotage rows, dead retention guard removed, gc test asserts, test count not hard-coded Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN * CI hardening: pin the third-party action by SHA, release_sandbox takes Fiji and QuPath refs as inputs Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN * Ledger row for the told TIFF fallback Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN --------- Co-authored-by: Claude <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What and why
Two worker-side changes to how an image input is read, from the findings of #123 (
docs/PERF_SHARED_MEMORY.mdsections 2, 4.5 and 6).1. Shared-memory
order(correctness). The worker ignored a descriptor'sorder, so an F-order block (what an ImgLib2-style[X, Y]host naturally has) was read transposed with no error: wrong science. NowC/C_ORDER(or no key) andF/F_ORDERare honoured: the block is read with the strides of the declared order and the tool gets the same logical array, as a C-ordered copy. Any other value ("A","K","f", a number, a list,null) is refused withunreadable_imageand a message sayingsend 'C' or 'F'. I chose honour-and-test because it is oneorder=argument; unknown values are refused either way. Documented indocs/PROTOCOL.md.2. Memory-mapped TIFF input. An image input given as a TIFF file of at least 8 MiB that is clearly the simple case (one series, one level, uncompressed, untiled, every page's strips in one contiguous run, native byte order, kind generic/ImageJ/shaped, not cut short) is mapped with
np.memmap(mode="c")instead of read and copied.Behaviour changes
tifffile.imread, a plain writablenumpy.ndarray. Decision: copy-on-write, not a read-only view. A read-only view would make a tool that today doesimage[mask] = 0on its input raise; copy-on-write keeps it working, and the first write copies the page privately so the file (the host's export or a person's own) never changes.tifffile.imreadpath for compressed, tiled, predictor, multi-series, pyramid, non-contiguous, OME, non-native byte order, small (< 8 MiB), cut-short files, and whenLC_TIFF_MEMMAP=0is set in the worker's environment.series.dataoffsettrusts the layout of a series from its first pages, so a stack whose later pages lie elsewhere would have been mapped to the wrong pixels. Every page's offsets are now checked (_pages_are_one_block; about 65 ms for a 5000-page stack), with a test on a patched file.convert.release_mapped_inputs()before every terminal message, so a failed tool whose traceback or a reference cycle holds the input does not keep the file locked (Windows) afterFAILURE. Documented limits in PROTOCOL.md: a tool that keeps its input in a global, and a host that truncates the file while a task runs (a mapped page past the new end ends the worker).benchmarks/tiff_memmap.pyfrom Research: shared memory for big images (issue #66), benchmarks and findings #123 and the real worker (load_inputs_sof COMPLETION):imread)load_inputs_smax())Tests
tests/test_input_loading.py(+tests/input_app/): F order read with a non-symmetric array in 2D and 3D, both spellings, C/absent, 10 refused values, through a real worker; mapped cases (u8/u16/i16/u32/f32/f64, stack, RGB, ImageJ hyperstack, BigTIFF, many strips) equal toimreadin shape/dtype/values and plain ndarray type; every fallback (zlib, tiled, predictor, a stack with a gap, two series, OME, opposite byte order, pyramid, small, cut-short, env switch) with the same result asimread; a tool writing to its input (in process and through a worker): file hash and mtime unchanged, file deletable afterwards; after both a completed and a failing task the worker has no mapping of the file (/proc/self/maps) and the file can be removed.tests/test_sabotage.py, 6 new breaks, all caught): order ignored, unknown order read as C, mapping openedr+, the page-gap check removed, mapping not released, mapping never used. Run locally withLC_SABOTAGE_ONLY.mainhere (see below); black, ruff, mypy, vulture as in the lint job.Not verified
os.removeafterFAILURE) is only exercised by the CI cells; nothing here ran on those systems. See CI below.drop_cachesin a sandbox VM, not a spinning or network disk; no timing on real host machines or with Defender.ImageJthat are covered by the ImageJ case only as written by tifffile (imagej=True).test_tools_features.py::test_doctor_prints_them_and_does_not_call_an_upgrade_stale: not a failure onmainin CI (green, full matrix, run 38356428622) nor in a clean virtualenv here. It fails when run with this sandbox's system Python: that interpreter has an older editable install of Tools (/tmp/wt_versions, same version string, withoutretention_prune) which thedoctorsubprocess imports instead of the checkout, so the printed feature list differs. An environment artefact, not changed here. (test_hardening...shared_entry_is_skippedfails onmaintoo when run as root in this sandbox; it is skipped on CI runners.)🤖 Generated with Claude Code
https://claude.ai/code/session_01Y2SN8SuEakTdiWy3F2WUqN
Generated by Claude Code