Skip to content

Close state storage in the UTXO and digest state property tests - #2460

Merged
kushti merged 1 commit into
ergoplatform:v6.0.4from
Ergologica:fix/close-state-storage-in-tests
Aug 10, 2026
Merged

Close state storage in the UTXO and digest state property tests#2460
kushti merged 1 commit into
ergoplatform:v6.0.4from
Ergologica:fix/close-state-storage-in-tests

Conversation

@Ergologica

Copy link
Copy Markdown
Contributor

The leak

Every createUtxoState opens a fresh LevelDB under a new temp dir. ErgoState.closeStorage() exists, but the only callers are in ErgoNodeViewHolderno test has ever closed one. Measured on master, 40 calls in a loop:

leaked: base=148 after=472  delta=324  -> 8.1 fds per createUtxoState
closed: base=472 after=472  delta=0    -> 0   fds, calling us.closeStorage()

UtxoStateSpecification and DigestStateSpecification have 14 properties between them doing forAll(boxesHolderGen), each opening a state per iteration at ScalaTest's default minSuccessful = 10. Nothing is released until the JVM exits.

The effect

Peak open file descriptors while running just these two suites, sampled from /proc/<pid>/fd every 300ms:

peak fds
master 2429
this branch 1019

A 58% drop from 20 added lines. For scale, the default limit on the container I measured this on is 4096 — two suites out of a ~740-test job were sitting at 59% of it.

I ran into this the hard way: a loop calling the UtxoStateSpecification property body 500 times died at roughly 450 with java.nio.file.FileSystemException: ... Too many open files.

The change

us.closeStorage() at the end of each forAll(boxesHolderGen) body, plus ds.close() where the property also builds a DigestState. Nothing else. DigestStateSpecification's reopen property already did exactly this — the convention existed, it just was not applied anywhere else.

Derived states share the parent's store, so one close per created store is enough and closing the original covers everything applyModifier / rollbackTo returned.

testOnly ... UtxoStateSpecification ... DigestStateSpecification — 27 tests, green.

Two honest notes

This may or may not fix the flaky CI. Run node tests fails intermittently in exactly these two suites — a different one each time — with IllegalArgumentException: requirement failed during forAll(boxesHolderGen) evaluation. Descriptor exhaustion would explain the "different suite each run" pattern, and it would explain why neither suite reproduces alone. But I could not reproduce the failure locally (300 generator runs and 500 full property runs, clean), so I am not claiming this is the cause. The leak is worth fixing on its own terms.

closeStorage() logs. It does log.warn("Closing state's store."), meant for node shutdown, so this adds ~140 WARN lines to the node test log. If that is unwelcome I am happy to switch to us.store.close(), or to move the log to debug in a separate commit — your call.

@kushti
kushti changed the base branch from master to v6.0.4 August 10, 2026 09:11
@kushti
kushti merged commit 0359bc3 into ergoplatform:v6.0.4 Aug 10, 2026
8 checks 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.

2 participants