Skip to content

Flip/rotation operations crash or hang in stand-alone (PyInstaller) version #304

@PierreRaybaut

Description

@PierreRaybaut

Describe the bug

In the stand-alone Windows version of DataLab (built with PyInstaller), image flip and rotation operations ("Flip horizontally", "Flip vertically", "Rotate 90° left/right", "Flip diagonally") either crash with an unhandled exception or hang indefinitely (the progress dialog with the Cancel button stays open and nothing happens).

This does not affect the Python package version of DataLab — only the frozen stand-alone executable.

To Reproduce

  1. Launch the stand-alone version of DataLab (DataLab_v1)
  2. Create a ramp image (or any image)
  3. Open the Processing menu (or Operations menu)
  4. Select Flip horizontally (or any flip/rotation operation)
  5. The application either:
    • Shows an error dialog with the traceback below, or
    • Hangs with the progress/cancel dialog open indefinitely (the computation never completes)

Expected behavior

The image should be flipped/rotated and the result displayed normally, as it does in the Python package version.

Error traceback

Traceback (most recent call last):
  File "multiprocessing\process.py", line 313, in _bootstrap
  File "multiprocessing\process.py", line 108, in run
  File "multiprocessing\pool.py", line 114, in worker
  File "multiprocessing\queues.py", line 387, in get
  File "pyimod02_importers.py", line 457, in exec_module
  File "datalab\gui\processor\image.py", line 34, in <module>
ImportError: cannot import name 'BaseProcessor' from partially initialized module
'datalab.gui.processor.base' (most likely due to a circular import)
(C:\Program Files (x86)\DataLab_v1\_internal\datalab\gui\processor\base.py)

A secondary error also appears during the application's error logging:

Traceback (most recent call last):
  File "start.pyw", line 26, in <module>
  ...
  File "datalab\gui\processor\base.py", line 231, in <module>
  File "pyi_rth_multiprocessing.py", line 48, in _freeze_support
  File "multiprocessing\spawn.py", line 122, in spawn_main
  File "multiprocessing\process.py", line 326, in _bootstrap
AttributeError: 'NoneType' object has no attribute 'write'

Screenshots

Image

Root cause analysis

Flip and rotation operations are the only image operations wrapped in a GeometricTransformWrapper class (defined in datalab/gui/processor/image.py), which applies geometry metadata transformations after the image data transformation. This wrapper is pickled and sent to the multiprocessing worker process.

In the PyInstaller frozen executable, when the worker process unpickles GeometricTransformWrapper, Python must import the module where the class is defined (datalab.gui.processor.image). This module imports BaseProcessor from datalab.gui.processor.base, which triggers the full DataLab GUI import chain inside the worker process. This causes:

  1. A circular import error because base.py is only partially initialized at that point
  2. multiprocessing.freeze_support() being called at module level in base.py during the child process bootstrap, causing the AttributeError: 'NoneType' object has no attribute 'write'
  3. In some configurations, the worker process crashes silently and the main process hangs indefinitely waiting for a result that will never come

Other processing operations (e.g., filters, normalization, FFT) are not affected because they are registered as plain Sigima functions that only require importing sigima.proc.image in the worker — a pure computation module with no DataLab GUI dependencies.

Fix

The fix involves moving GeometricTransformWrapper and apply_geometry_transform to a new standalone module (datalab/gui/processor/geometry_postprocess.py) that has no dependency on BaseProcessor, Qt, or PlotPy. When the worker unpickles the wrapper, it now only imports this lightweight module instead of the full GUI chain.

Installation information

  • DataLab installation type: stand-alone Windows version (PyInstaller)
  • Reproduced on: Windows 10, Windows 11 (multiple machines, both networked and isolated)

Additional context

Reported by end users on multiple machines at different sites. The bug is specific to the PyInstaller build because in standard Python execution, freeze_support() is a no-op and the multiprocessing spawn method re-executes the script entry point (which is protected by if __name__ == '__main__'), whereas in frozen builds the child process re-enters the import chain directly.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions