From 46f314ea3563cbfdf7a41f1f04aad05dfc69c81f Mon Sep 17 00:00:00 2001 From: Danny Yoo Date: Sun, 4 Dec 2011 20:04:03 -0500 Subject: [PATCH] chasing a double-release --- js-assembler/runtime-src/baselib-functions.js | 39 ++++++++++++------- js-assembler/runtime-src/runtime.js | 21 ++++++---- version.rkt | 2 +- 3 files changed, 40 insertions(+), 22 deletions(-) diff --git a/js-assembler/runtime-src/baselib-functions.js b/js-assembler/runtime-src/baselib-functions.js index b95e4a5..6576b84 100644 --- a/js-assembler/runtime-src/baselib-functions.js +++ b/js-assembler/runtime-src/baselib-functions.js @@ -128,16 +128,24 @@ var coerseClosureToJavaScript = function (v, MACHINE) { var f = function (succ, fail) { + var args = []; + var i; + for (i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + MACHINE.exclusiveLock.acquire( "js-as-closure", function(releaseLock) { succ = succ || function () {}; fail = fail || function () {}; + + releaseLock(); - if (!(baselib.arity.isArityMatching(v.racketArity, arguments.length - 2))) { + if (!(baselib.arity.isArityMatching(v.racketArity, args.length - 2))) { var msg = baselib.format.format( "arity mismatch: ~s expected ~s argument(s) but received ~s", - [v.displayName, v.racketArity, arguments.length - 2]); + [v.displayName, v.racketArity, args.length - 2]); return fail(new baselib.exceptions.RacketError( msg, baselib.exceptions.makeExnFailContractArity(msg, @@ -177,10 +185,10 @@ MACHINE.c.push( new baselib.frames.CallFrame(afterGoodInvoke, v)); - MACHINE.a = arguments.length - 2; + MACHINE.a = args.length - 2; var i; - for (i = 0; i < arguments.length - 2; i++) { - MACHINE.e.push(arguments[arguments.length - 1 - i]); + for (i = 0; i < args.length - 2; i++) { + MACHINE.e.push(args[args.length - 1 - i]); } MACHINE.p = v; MACHINE.params['currentErrorHandler'] = function (MACHINE, e) { @@ -191,7 +199,6 @@ fail(e); }; - releaseLock(); MACHINE.trampoline(v.label); }); }; @@ -222,15 +229,20 @@ // internallCallDuringPause: call a Racket procedure and get its results. // The use assumes the machine is in a running-but-paused state. var internalCallDuringPause = function (MACHINE, proc, success, fail) { - MACHINE.exclusiveLock.acquire( + var args = []; + var i; + for (i = 0; i < arguments.length; i++) { + args.push(arguments[i]); + } + MACHINE.exclusiveLock.acquire( "internal call during pause", function(releaseLock) { - + releaseLock(); var i; var oldArgcount, oldVal, oldProc, oldErrorHandler; - if (! baselib.arity.isArityMatching(proc.racketArity, arguments.length - 4)) { + if (! baselib.arity.isArityMatching(proc.racketArity, args.length - 4)) { var msg = baselib.format.format("arity mismatch: ~s expected ~s arguments, but received ~s", - [proc.displayName, proc.racketArity, arguments.length - 4]); + [proc.displayName, proc.racketArity, args.length - 4]); return fail(baselib.exceptions.makeExnFailContractArity(msg, MACHINE.captureContinuationMarks())); } @@ -268,9 +280,9 @@ MACHINE.c.push( new baselib.frames.CallFrame(afterGoodInvoke, proc)); - MACHINE.a = arguments.length - 4; - for (i = 0; i < arguments.length - 4; i++) { - MACHINE.e.push(arguments[arguments.length - 1 - i]); + MACHINE.a = args.length - 4; + for (i = 0; i < args.length - 4; i++) { + MACHINE.e.push(args[args.length - 1 - i]); } MACHINE.p = proc; MACHINE.params['currentErrorHandler'] = function (MACHINE, e) { @@ -281,7 +293,6 @@ fail(e); }; - releaseLock(); MACHINE.trampoline(proc.label); } else { diff --git a/js-assembler/runtime-src/runtime.js b/js-assembler/runtime-src/runtime.js index 398fb9e..9045c05 100644 --- a/js-assembler/runtime-src/runtime.js +++ b/js-assembler/runtime-src/runtime.js @@ -191,29 +191,36 @@ if (id === undefined) { id = ExclusiveLock.makeRandomNonce(); } + + var alreadyReleased = false; + // Allow for re-entrancy if the id is the same as the // entity who is locking. if (this.locked === false || this.locked === id) { this.locked = id; - setTimeout( + onAcquire.call( + that, + // releaseLock function() { - onAcquire.call( - that, - // NOTE: the caller must release the lock or else deadlock! + setTimeout( function() { var waiter; + if (alreadyReleased) { + throw new Error( + "Internal error: trying to release the lock, but already released"); + } if (that.locked === false) { throw new Error( "Internal error: trying to unlock the lock, but already unlocked"); } that.locked = false; + alreadyReleased = true; if (that.waiters.length > 0) { waiter = that.waiters.shift(); that.acquire(waiter.id, waiter.onAcquire); } - }); - }, - 0); + }, 0); + }); } else { this.waiters.push({ id: id, onAcquire: onAcquire } ); diff --git a/version.rkt b/version.rkt index 750354d..f14d333 100644 --- a/version.rkt +++ b/version.rkt @@ -7,4 +7,4 @@ (provide version) (: version String) -(define version "1.100") +(define version "1.101")