Skip to content

Fix save_binary TypeError on objects holding a Cluster#415

Merged
mesonepigreco merged 2 commits into
SSCHAcode:masterfrom
krystophny:fix-save-binary-cluster-lock
Jun 10, 2026
Merged

Fix save_binary TypeError on objects holding a Cluster#415
mesonepigreco merged 2 commits into
SSCHAcode:masterfrom
krystophny:fix-save-binary-cluster-lock

Conversation

@krystophny

Copy link
Copy Markdown
Contributor

Fixes #114.

sscha.Utilities.save_binary raised TypeError: cannot pickle '_thread.lock' object when saving a sscha.Relax.SSCHA object after a relaxation. The lock comes from Cluster.compute_ensemble_batch, which sets self.lock = threading.Lock() and never clears it, so any object referencing the cluster after a calculation cannot be pickled.

Instead of replacing pickle with dill, this adds __getstate__/__setstate__ to sscha.Cluster.Cluster. The lock is transient runtime state: it is dropped on save and reset to None on load (the same value __init__ assigns), and compute_ensemble_batch recreates it on the next run. Plain pickle now round-trips, existing binaries stay loadable, and the restored object remains usable (see also #105).

A regression test in tests/test_save_binary/ builds a minimal relax object from Examples/ensemble_data_test with a cluster in the post-calculation state, saves it with save_binary, reloads it with load_binary, and checks the restored state.

Verification

Before the fix:

$ python tests/test_save_binary/test_save_binary.py
Traceback (most recent call last):
  File "tests/test_save_binary/test_save_binary.py", line 50, in test_save_binary_relax_with_cluster
    sscha.Utilities.save_binary(relax, filename)
  File "Modules/Utilities.py", line 663, in save_binary
    pickle.dump(object, open(filename, "wb"))
TypeError: cannot pickle '_thread.lock' object

$ pytest -q tests/test_save_binary
FAILED test_save_binary.py::test_save_binary_relax_with_cluster - TypeError: ...
1 failed, 2 warnings in 0.95s

After the fix:

$ python tests/test_save_binary/test_save_binary.py
save_binary/load_binary round trip succeeded

$ pytest -q tests/test_save_binary
1 passed, 2 warnings in 0.91s

$ cd tests && OMP_NUM_THREADS=1 pytest -q -m "not release" --ignore=aiida_ensemble
23 passed, 1 skipped, 1 deselected, 29 warnings in 95.75s (0:01:35)

Cluster.compute_ensemble_batch stores a threading.Lock on the cluster
and never clears it, so sscha.Utilities.save_binary failed with
TypeError: cannot pickle '_thread.lock' object on any relax or
minimizer object holding a cluster after a calculation.

Add __getstate__/__setstate__ on Cluster that drop the lock on save
and reset it to None on load, matching the state after __init__.
compute_ensemble_batch recreates the lock when needed, so plain
pickle round trips work and the restored object stays usable.

Fixes SSCHAcode#114
@mesonepigreco mesonepigreco self-assigned this Jun 10, 2026
@mesonepigreco mesonepigreco self-requested a review June 10, 2026 16:59
@mesonepigreco mesonepigreco added this to the 1.7 milestone Jun 10, 2026

@mesonepigreco mesonepigreco left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The edits are extremely local; the test suite also passes in the GitHub workflow.
It is safe to approve.

Thanks a lot! :)

@mesonepigreco mesonepigreco merged commit aa725e6 into SSCHAcode:master Jun 10, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

sscha.Utilities.save_binary throws TypeError: cannot pickle '_thread.lock' object when trying to save sscha.Relax.SSCHA object into file

2 participants