Skip to content

Commit ca282cd

Browse files
committed
The list of FinalizerReference should be kept per RubyContext
* Otherwise accesses to the list will not be synchronized correctly.
1 parent 2d1f4ea commit ca282cd

File tree

1 file changed

+21
-17
lines changed

1 file changed

+21
-17
lines changed

src/main/java/org/truffleruby/core/FinalizationService.java

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ public DynamicObject getRoot() {
5555

5656
public static class FinalizerReference extends PhantomReference<Object> {
5757

58-
private static FinalizerReference first = null;
59-
6058
/**
6159
* All accesses to this Deque must be synchronized by taking the
6260
* {@link FinalizationService} monitor, to avoid concurrent access.
6361
*/
6462
private final Deque<Finalizer> finalizers = new LinkedList<>();
63+
64+
/** The doubly-linked list of FinalizerReference, needed to collect finalizer Procs for ObjectSpace. */
6565
private FinalizerReference next = null;
6666
private FinalizerReference prev = null;
6767

@@ -73,10 +73,11 @@ private void addFinalizer(Class<?> owner, Runnable action, DynamicObject root) {
7373
finalizers.addLast(new Finalizer(owner, action, root));
7474
}
7575

76-
private FinalizerReference removeFinalizers(Class<?> owner) {
76+
private FinalizerReference removeFinalizers(FinalizationService finalizationService, Class<?> owner) {
7777
finalizers.removeIf(f -> f.getOwner() == owner);
78+
7879
if (finalizers.isEmpty()) {
79-
remove(this);
80+
finalizationService.remove(this);
8081
return null;
8182
} else {
8283
return this;
@@ -99,7 +100,10 @@ private void collectRoots(Collection<DynamicObject> roots) {
99100

100101
private final RubyContext context;
101102
private final ReferenceQueue<Object> finalizerQueue = new ReferenceQueue<>();
103+
/** The finalizer Ruby thread, spawned lazily. */
102104
private DynamicObject finalizerThread;
105+
/** The head of a doubly-linked list of FinalizerReference, needed to collect finalizer Procs for ObjectSpace. */
106+
private FinalizerReference first = null;
103107

104108
public FinalizationService(RubyContext context) {
105109
this.context = context;
@@ -109,7 +113,7 @@ public synchronized FinalizerReference addFinalizer(Object object, FinalizerRefe
109113

110114
if (finalizerReference == null) {
111115
finalizerReference = new FinalizerReference(object, finalizerQueue);
112-
FinalizationService.add(finalizerReference);
116+
add(finalizerReference);
113117
}
114118

115119
finalizerReference.addFinalizer(owner, action, root);
@@ -166,7 +170,7 @@ private void createFinalizationThread() {
166170
}
167171

168172
private void runFinalizer(FinalizerReference finalizerReference) {
169-
FinalizationService.remove(finalizerReference);
173+
remove(finalizerReference);
170174

171175
try {
172176
while (!context.isFinalizing()) {
@@ -193,7 +197,7 @@ private void runFinalizer(FinalizerReference finalizerReference) {
193197
}
194198

195199
public synchronized void collectRoots(Collection<DynamicObject> roots) {
196-
FinalizerReference finalizerReference = FinalizerReference.first;
200+
FinalizerReference finalizerReference = first;
197201
while (finalizerReference != null) {
198202
finalizerReference.collectRoots(roots);
199203
finalizerReference = finalizerReference.next;
@@ -202,24 +206,24 @@ public synchronized void collectRoots(Collection<DynamicObject> roots) {
202206

203207
public synchronized FinalizerReference removeFinalizers(Object object, FinalizerReference ref, Class<?> owner) {
204208
if (ref != null) {
205-
return ref.removeFinalizers(owner);
209+
return ref.removeFinalizers(this, owner);
206210
} else {
207211
return null;
208212
}
209213
}
210214

211-
private static synchronized void remove(FinalizerReference ref) {
215+
private synchronized void remove(FinalizerReference ref) {
212216
if (ref.next == ref) {
213217
// Already removed.
214218
return;
215219
}
216220

217-
if (FinalizerReference.first == ref) {
221+
if (first == ref) {
218222
if (ref.next != null) {
219-
FinalizerReference.first = ref.next;
223+
first = ref.next;
220224
} else {
221225
// The list becomes empty
222-
FinalizerReference.first = null;
226+
first = null;
223227
}
224228
}
225229

@@ -235,12 +239,12 @@ private static synchronized void remove(FinalizerReference ref) {
235239
ref.prev = ref;
236240
}
237241

238-
private static synchronized void add(FinalizerReference newRef) {
239-
if (FinalizerReference.first != null) {
240-
newRef.next = FinalizerReference.first;
241-
FinalizerReference.first.prev = newRef;
242+
private synchronized void add(FinalizerReference newRef) {
243+
if (first != null) {
244+
newRef.next = first;
245+
first.prev = newRef;
242246
}
243-
FinalizerReference.first = newRef;
247+
first = newRef;
244248
}
245249

246250
}

0 commit comments

Comments
 (0)