Skip to content

Commit

Permalink
Object safepoint operations need to be in finally blocks consistently
Browse files Browse the repository at this point in the history
This is a correctness precaution.
All subsequent register/unregister operations following an initial unregister/register need to be in a finally clause if the operations in-between could cause any kind of exception, which most can.

For consistency, it should be used really everywhere.

There are only two points where it might be acceptable, but should be still fixed: init of object system, and in the executeApplication method.

Signed-off-by: Stefan Marr <git@stefan-marr.de>
  • Loading branch information
smarr committed Apr 16, 2020
1 parent 352e0e6 commit dd07d87
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 33 deletions.
26 changes: 15 additions & 11 deletions src/som/interpreter/actors/Actor.java
Expand Up @@ -259,6 +259,19 @@ void doRun() {
ObjectTransitionSafepoint.INSTANCE.register();

ActorProcessingThread t = (ActorProcessingThread) Thread.currentThread();
try {
doRunWithObjectSafepoints(t);
} finally {
ObjectTransitionSafepoint.INSTANCE.unregister();

if (VmSettings.ACTOR_TRACING || VmSettings.KOMPOS_TRACING) {
t.swapTracingBufferIfRequestedUnsync();
}
t.currentlyExecutingActor = null;
}
}

public void doRunWithObjectSafepoints(final ActorProcessingThread t) {
WebDebugger dbg = null;
if (VmSettings.TRUFFLE_DEBUGGER_ENABLED) {
dbg = vm.getWebDebugger();
Expand All @@ -273,18 +286,9 @@ void doRun() {
KomposTrace.currentActivity(actor);
}

try {
while (getCurrentMessagesOrCompleteExecution()) {
processCurrentMessages(t, dbg);
}
} finally {
ObjectTransitionSafepoint.INSTANCE.unregister();
}

if (VmSettings.ACTOR_TRACING || VmSettings.KOMPOS_TRACING) {
t.swapTracingBufferIfRequestedUnsync();
while (getCurrentMessagesOrCompleteExecution()) {
processCurrentMessages(t, dbg);
}
t.currentlyExecutingActor = null;
}

protected void processCurrentMessages(final ActorProcessingThread currentThread,
Expand Down
16 changes: 8 additions & 8 deletions src/som/interpreter/processes/SChannel.java
Expand Up @@ -86,11 +86,11 @@ public SChannelInput(final SynchronousQueue<Object> cell,
public Object read(final RecordTwoEvent traceRead) throws InterruptedException {
ObjectTransitionSafepoint.INSTANCE.unregister();

if (VmSettings.REPLAY) {
ReplayData.replayDelayNumberedEvent(this, channel.getId());
}

try {
if (VmSettings.REPLAY) {
ReplayData.replayDelayNumberedEvent(this, channel.getId());
}

synchronized (this) {
if (VmSettings.ACTOR_TRACING) {
traceRead.record(channel.getId(), numReads);
Expand Down Expand Up @@ -161,11 +161,11 @@ public void write(final Object value, final RecordTwoEvent traceWrite)
throws InterruptedException {
ObjectTransitionSafepoint.INSTANCE.unregister();

if (VmSettings.REPLAY) {
ReplayData.replayDelayNumberedEvent(this, channel.getId());
}

try {
if (VmSettings.REPLAY) {
ReplayData.replayDelayNumberedEvent(this, channel.getId());
}

synchronized (this) {
if (VmSettings.ACTOR_TRACING) {
traceWrite.record(channel.getId(), numWrites);
Expand Down
4 changes: 2 additions & 2 deletions src/som/primitives/threading/ConditionPrimitives.java
Expand Up @@ -47,9 +47,9 @@ public final Condition doCondition(final Condition cond) {
cond.await();
} catch (InterruptedException e) {
/* doesn't tell us a lot at the moment, so it is ignored */
} finally {
ObjectTransitionSafepoint.INSTANCE.register();
}

ObjectTransitionSafepoint.INSTANCE.register();
return cond;
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/som/primitives/threading/DelayPrimitives.java
Expand Up @@ -23,8 +23,9 @@ public final SObjectWithoutFields doLong(final long milliseconds) {
Thread.sleep(milliseconds);
} catch (InterruptedException e) {
/* Not relevant for the moment */
} finally {
ObjectTransitionSafepoint.INSTANCE.register();
}
ObjectTransitionSafepoint.INSTANCE.register();
return Nil.nilObject;
}
}
Expand Down
20 changes: 13 additions & 7 deletions src/tools/concurrency/TracingActors.java
Expand Up @@ -375,22 +375,28 @@ private static void removeFirstExpectedMessage(final ReplayActor a) {
private MessageRecord getExpected() {
if (expectedMessages.isEmpty()) {
ObjectTransitionSafepoint.INSTANCE.unregister();
while (traceParser.getMoreEventsForEntity(getId())
&& expectedMessages.isEmpty()) {
// NOOP
try {
while (traceParser.getMoreEventsForEntity(getId())
&& expectedMessages.isEmpty()) {
// NOOP
}
} finally {
ObjectTransitionSafepoint.INSTANCE.register();
}
ObjectTransitionSafepoint.INSTANCE.register();
}
return expectedMessages.poll();
}

private MessageRecord peekExpected() {
if (expectedMessages.isEmpty()) {
ObjectTransitionSafepoint.INSTANCE.unregister();
while (traceParser.getMoreEventsForEntity(getId()) && expectedMessages.isEmpty()) {
// NOOP
try {
while (traceParser.getMoreEventsForEntity(getId()) && expectedMessages.isEmpty()) {
// NOOP
}
} finally {
ObjectTransitionSafepoint.INSTANCE.register();
}
ObjectTransitionSafepoint.INSTANCE.register();
}
return expectedMessages.peek();
}
Expand Down
14 changes: 10 additions & 4 deletions src/tools/debugger/frontend/Suspension.java
Expand Up @@ -146,8 +146,17 @@ private void submitTask(final ApplicationThreadTask task) {
public void suspend() {
// don't participate in safepoints while being suspended
ObjectTransitionSafepoint.INSTANCE.unregister();
activityThread.markThreadAsSuspendedInDebugger();

try {
activityThread.markThreadAsSuspendedInDebugger();
suspendWithoutObjectSafepoints();
} finally {
activityThread.markThreadAsResumedFromDebugger();
ObjectTransitionSafepoint.INSTANCE.register();
}
}

public void suspendWithoutObjectSafepoints() {
boolean continueWaiting = true;
while (continueWaiting) {
try {
Expand All @@ -174,9 +183,6 @@ public void suspend() {
suspendedEvent = null;
stack = null;
}

activityThread.markThreadAsResumedFromDebugger();
ObjectTransitionSafepoint.INSTANCE.register();
}

public TracingActivityThread getActivityThread() {
Expand Down

0 comments on commit dd07d87

Please sign in to comment.