@@ -101,7 +101,8 @@ public synchronized void close() {
101101 closed = true ;
102102 store .unregisterTransaction (this );
103103
104- if (!nativeIsOwnerThread (transaction )) {
104+ boolean isOwnerThread = nativeIsOwnerThread (transaction );
105+ if (!isOwnerThread ) {
105106 boolean isActive = nativeIsActive (transaction );
106107 boolean isRecycled = nativeIsRecycled (transaction );
107108 if (isActive || isRecycled ) {
@@ -126,6 +127,27 @@ public synchronized void close() {
126127 // TODO not destroying is probably only a small leak on rare occasions, but still could be fixed
127128 if (!store .isNativeStoreClosed ()) {
128129 nativeDestroy (transaction );
130+ } else {
131+ String threadType = isOwnerThread ? "owner thread" : "non-owner thread" ;
132+ if (readOnly ) {
133+ // Minor leak, but still print it so we can check logs: it should only happen occasionally.
134+ // We cannot rely on the store waiting for read transactions; it only waits for a limited time.
135+ System .out .println ("Info: closing read transaction after store was closed (should be avoided) in " +
136+ threadType );
137+ System .out .flush ();
138+ } else { // write transaction
139+ System .out .println ("WARN: closing write transaction after store was closed (must be avoided) in " +
140+ threadType );
141+ System .out .flush ();
142+ if (store .isNativeStoreDestroyed ()) {
143+ // This is an internal validation: if this is a write-TX,
144+ // the (native) store will always wait for it, so it must not be destroyed yet.
145+ // If this ever happens, the above assumption is wrong, and it probably prevents a SIGSEGV.
146+ throw new IllegalStateException (
147+ "Cannot destroy write transaction for an already destroyed store" );
148+ }
149+ nativeDestroy (transaction );
150+ }
129151 }
130152 }
131153 }
0 commit comments