Move the waitSetAppend subroutine call ahead of clearing the monitor
owner. We want waitSetAppend to check the invariant that the monitor
must be owned by the calling thread. Clearing the owner field prior
to the call breaks this invariant and causes a assertion to fail.
diff --git a/vm/Sync.c b/vm/Sync.c
index b7a83bd..16875e4 100644
--- a/vm/Sync.c
+++ b/vm/Sync.c
@@ -598,12 +598,13 @@
* release our hold. We need to let it go even if we're a few levels
* deep in a recursive lock, and we need to restore that later.
*
- * The order of operations here isn't significant, because we still
- * hold the pthread mutex.
+ * We append to the wait set ahead of clearing the count and owner
+ * fields so the subroutine can check that the calling thread owns
+ * the monitor. Aside from that, the order of member updates is
+ * not order sensitive as we hold the pthread mutex.
*/
- int prevLockCount;
-
- prevLockCount = mon->lockCount;
+ waitSetAppend(mon, self);
+ int prevLockCount = mon->lockCount;
mon->lockCount = 0;
mon->owner = NULL;
@@ -639,8 +640,6 @@
goto done;
}
- waitSetAppend(mon, self);
-
/*
* Release the monitor lock and wait for a notification or
* a timeout to occur.
@@ -670,9 +669,9 @@
/* Reacquire the monitor lock. */
lockMonitor(self, mon);
+done:
waitSetRemove(mon, self);
-done:
/*
* Put everything back. Again, we hold the pthread mutex, so the order
* here isn't significant.