Skip to content

Pitfalls observed by a colleague #25

@ctrueden

Description

@ctrueden
  1. All Python stdout goes to Appose protocol -- logging MUST use sys.stderr, never print() or sys.stdout
  2. NumPy pre-warm required on Windows -- prepend import numpy in init() before any NumPy-using scripts. Since init() replaces on each call, combine into a single call: init("import numpy\n" + mainScript)
  3. init() is lazy -- does NOT start Python or execute scripts. You MUST run a blocking task().waitFor() after init() to verify the environment. Without this, initialize() returns "success" in milliseconds without ever starting Python.
  4. init() replaces, does not append -- calling init() twice silently discards the first script. Our Windows NumPy workaround was being silently lost before this was discovered.
  5. NDArray must be closed -- shared memory leaks if close() is not called
  6. Multi-threaded worker requires serialization -- Appose runs each task() in its own thread within a single Python subprocess. Without inference_lock, concurrent overlay tiles race on model loading, CUDA memory, and forward passes. All GPU-accessing scripts must use with inference_lock:. Concurrent tasks in the same subprocess can cause Appose IPC message ordering races ("thread death").
  7. ServiceLoader classloader isolation -- NDArray allocation triggers ServiceLoader.load(ShmFactory.class) on every call with no caching. Must set TCCL to extension classloader.
  8. init_services.py must propagate ImportErrors -- if critical packages (torch, smp) are missing, the init script must fail loudly. Only catch runtime errors (no GPU, etc.) so the Java side knows the environment is broken.
  9. task.inputs is private in 0.10.0 -- Python scripts CANNOT use task.inputs["key"]. Inputs are injected directly into the script's execution scope as variables. Use model_path directly instead of task.inputs["model_path"]. For optional inputs, use try: reflection_padding / except NameError: reflection_padding = 0. task.outputs remains public and writable.
  10. Init script exports STRIP underscore-prefixed names -- Appose's python_worker explicitly filters out names starting with _ when exporting init script globals to task scripts: if not key.startswith('_'). This means _my_var defined in init_services.py is INVISIBLE to task scripts, while my_var is visible. NEVER use underscore-prefixed names for globals that task scripts need.

For each of these, consider whether and how to modify Appose to ease future pain.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions