def run(self, unused): from typhon.objects.collections.maps import EMPTY_MAP if self.done: return if self._ref.isResolved(): if isBroken(self._ref): f = self._eb else: f = self._cb try: outcome = f.call(u"run", [self._ref]) if not isBroken(self._ref) and isBroken(outcome): # success arm returned a broken promise outcome = self._eb.call(u"run", [outcome]) self._resolver.resolve(outcome) except UserException as ue: from typhon.objects.exceptions import sealException if not isBroken(self._ref): # success arm threw try: self._resolver.resolve(self._eb.call(u"run", [UnconnectedRef(currentVat.get(), sealException(ue))])) except UserException as ue2: self._resolver.smash(sealException(ue2)) else: # failure arm threw self._resolver.smash(sealException(ue)) self.done = True else: self.vat.sendOnly(self._ref, _WHENMORERESOLVED_1, [self], EMPTY_MAP)
def takeTurn(self): from typhon.objects.exceptions import sealException from typhon.objects.refs import Promise, resolution with self._pendingLock: resolver, target, atom, args, namedArgs = self._pending.pop(0) # Set up our Miranda FAIL. if namedArgs.extractStringKey(u"FAIL", None) is None: if resolver is not None: FAIL = resolver.makeSmasher() else: from typhon.objects.ejectors import theThrower FAIL = theThrower namedArgs = namedArgs.withStringKey(u"FAIL", FAIL) # If the target is a promise, then we should send to it instead of # calling. Try to resolve it as much as possible first, though. target = resolution(target) # self.log(u"Taking turn: %s<-%s(%s) (resolver: %s)" % # (target.toQuote(), atom.verb, # u", ".join([arg.toQuote() for arg in args]), # u"yes" if resolver is not None else u"no")) try: if isinstance(target, Promise): if resolver is None: target.sendOnly(atom, args, namedArgs) else: result = target.send(atom, args, namedArgs) # The resolver may have already been invoked, so we'll use # .resolveRace/1 instead of .resolve/1. ~ C. resolver.resolveRace(result) else: result = target.callAtom(atom, args, namedArgs) if resolver is not None: # Same logic as above. resolver.resolveRace(result) except UserException as ue: if resolver is not None: resolver.smash(sealException(ue)) else: self.log(u"Uncaught user exception while taking turn" u" (and no resolver): %s" % ue.formatError().decode("utf-8"), tags=["serious"]) except VatCheckpointed: self.log(u"Ran out of checkpoints while taking turn", tags=["serious"]) if resolver is not None: resolver.smash( sealException(userError(u"Vat ran out of checkpoints"))) except Ejecting: self.log(u"Ejector tried to escape vat turn boundary", tags=["serious"]) if resolver is not None: resolver.smash( sealException( userError(u"Ejector tried to escape from vat")))
def takeTurn(self): from typhon.objects.exceptions import sealException from typhon.objects.refs import Promise, resolution with self._pendingLock: resolver, target, atom, args, namedArgs = self._pending.pop(0) # Set up our Miranda FAIL. if namedArgs.extractStringKey(u"FAIL", None) is None: if resolver is not None: FAIL = resolver.makeSmasher() else: from typhon.objects.ejectors import theThrower FAIL = theThrower namedArgs = namedArgs.withStringKey(u"FAIL", FAIL) # If the target is a promise, then we should send to it instead of # calling. Try to resolve it as much as possible first, though. target = resolution(target) # self.log(u"Taking turn: %s<-%s(%s) (resolver: %s)" % # (target.toQuote(), atom.verb, # u", ".join([arg.toQuote() for arg in args]), # u"yes" if resolver is not None else u"no")) try: if isinstance(target, Promise): if resolver is None: target.sendOnly(atom, args, namedArgs) else: result = target.send(atom, args, namedArgs) # The resolver may have already been invoked, so we'll use # .resolveRace/1 instead of .resolve/1. ~ C. resolver.resolveRace(result) else: result = target.callAtom(atom, args, namedArgs) if resolver is not None: # Same logic as above. resolver.resolveRace(result) except UserException as ue: if resolver is not None: resolver.smash(sealException(ue)) else: self.log(u"Uncaught user exception while taking turn" u" (and no resolver): %s" % ue.formatError().decode("utf-8"), tags=["serious"]) except VatCheckpointed: self.log(u"Ran out of checkpoints while taking turn", tags=["serious"]) if resolver is not None: resolver.smash(sealException(userError(u"Vat ran out of checkpoints"))) except Ejecting: self.log(u"Ejector tried to escape vat turn boundary", tags=["serious"]) if resolver is not None: resolver.smash(sealException(userError(u"Ejector tried to escape from vat")))
def unwind(self, machine, ex): machine.env.restoreDepth(self.savedDepth) # Push the caught value. machine.push(sealException(ex)) # And the ejector. machine.push(NullObject) return self.index
def _resolve(self, target, strict=True): if self._ref is None: if strict: raise userError(u"Already resolved") return False else: if self.guard is not None and not isinstance(target, UnconnectedRef): # Coerce. If there's a problem, then smash the promise. with Ejector() as ej: try: target = self.guard.call(u"coerce", [target, ej]) except Ejecting as e: if e.ejector is not ej: raise target = UnconnectedRef(self.vat, e.value) except UserException as ue: from typhon.objects.exceptions import sealException target = UnconnectedRef(self.vat, sealException(ue)) self._ref.setTarget(_toRef(target, self.vat)) self._ref.commit() self._buf.deliverAll(target) self._ref = None self._buf = None return True
def run(self, unused): from typhon.objects.collections.maps import EMPTY_MAP if self.done: return if self._ref.state() is NEAR: try: outcome = self._cb.call(u"run", [self._ref]) if self._resolver is not None: self._resolver.resolve(outcome) except UserException as ue: if self._resolver is None: raise else: from typhon.objects.exceptions import sealException self._resolver.smash(sealException(ue)) self.done = True elif self._ref.state() is BROKEN: if self._resolver is not None: self._resolver.resolve(self._ref) self.done = True else: self.vat.sendOnly(self._ref, _WHENMORERESOLVED_1, [self], EMPTY_MAP)
def run(self, unused): from typhon.objects.collections.maps import EMPTY_MAP if not isinstance(self._ref, Promise): # Near refs can't possibly be broken. return if self._ref.state() is EVENTUAL: self.vat.sendOnly(self._ref, _WHENMORERESOLVED_1, [self], EMPTY_MAP) elif self._ref.state() is BROKEN: try: # Deliver the brokenness notification. outcome = self._cb.call(u"run", [self._ref]) if self._resolver is not None: # Success. self._resolver.resolve(outcome) except UserException as ue: # Failure. Continue delivering failures. from typhon.objects.exceptions import sealException self._resolver.smash(sealException(ue))
def takeTurn(self): from typhon.objects.refs import Promise, resolution with self._pendingLock: resolver, target, atom, args, namedArgs = self._pending.pop(0) # If the target is a promise, then we should send to it instead of # calling. Try to resolve it as much as possible first, though. target = resolution(target) self.log(u"Taking turn: %s<-%s(%s) (resolver: %s)" % (target.toQuote(), atom.verb, u", ".join([arg.toQuote() for arg in args]), u"yes" if resolver is not None else u"no")) if resolver is None: try: # callOnly/sendOnly. if isinstance(target, Promise): target.sendOnly(atom, args, namedArgs) else: # Oh, that's right; we don't do callOnly since it's silly. target.callAtom(atom, args, namedArgs) except UserException as ue: self.log(u"Uncaught user exception while taking turn" u" (and no resolver): %s" % ue.formatError().decode("utf-8"), tags=["serious"]) except VatCheckpointed: self.log(u"Ran out of checkpoints while taking turn", tags=["serious"]) except Ejecting: self.log(u"Ejector tried to escape vat turn boundary", tags=["serious"]) else: from typhon.objects.collections.maps import ConstMap, monteMap from typhon.objects.exceptions import sealException from typhon.objects.refs import Smash # XXX monteMap() _d = monteMap() _d[StrObject(u"FAIL")] = Smash(resolver) MIRANDA_ARGS = ConstMap(_d) namedArgs = namedArgs._or(MIRANDA_ARGS) try: # call/send. if isinstance(target, Promise): result = target.send(atom, args, namedArgs) else: result = target.callAtom(atom, args, namedArgs) # Resolver may be invoked from the code in this turn, so # strict=False to skip this if already resolved. resolver.resolve(result, strict=False) except UserException as ue: resolver.smash(sealException(ue)) except VatCheckpointed: self.log(u"Ran out of checkpoints while taking turn; breaking resolver", tags=["serious"]) resolver.smash(sealException(userError(u"Vat ran out of checkpoints"))) except Ejecting: self.log(u"Ejector tried to escape vat turn boundary", tags=["serious"]) resolver.smash(sealException(userError(u"Ejector tried to escape from vat")))
def takeTurn(self): from typhon.objects.refs import Promise, resolution with self._pendingLock: resolver, target, atom, args, namedArgs = self._pending.pop(0) # If the target is a promise, then we should send to it instead of # calling. Try to resolve it as much as possible first, though. target = resolution(target) self.log( u"Taking turn: %s<-%s(%s) (resolver: %s)" % (target.toQuote(), atom.verb, u", ".join( [arg.toQuote() for arg in args]), u"yes" if resolver is not None else u"no")) if resolver is None: try: # callOnly/sendOnly. if isinstance(target, Promise): target.sendOnly(atom, args, namedArgs) else: # Oh, that's right; we don't do callOnly since it's silly. target.callAtom(atom, args, namedArgs) except UserException as ue: self.log(u"Uncaught user exception while taking turn" u" (and no resolver): %s" % ue.formatError().decode("utf-8"), tags=["serious"]) except VatCheckpointed: self.log(u"Ran out of checkpoints while taking turn", tags=["serious"]) except Ejecting: self.log(u"Ejector tried to escape vat turn boundary", tags=["serious"]) else: from typhon.objects.collections.maps import ConstMap, monteMap from typhon.objects.exceptions import sealException from typhon.objects.refs import Smash # XXX monteMap() _d = monteMap() _d[StrObject(u"FAIL")] = Smash(resolver) MIRANDA_ARGS = ConstMap(_d) namedArgs = namedArgs._or(MIRANDA_ARGS) try: # call/send. if isinstance(target, Promise): result = target.send(atom, args, namedArgs) else: result = target.callAtom(atom, args, namedArgs) # Resolver may be invoked from the code in this turn, so # strict=False to skip this if already resolved. resolver.resolve(result, strict=False) except UserException as ue: resolver.smash(sealException(ue)) except VatCheckpointed: self.log( u"Ran out of checkpoints while taking turn; breaking resolver", tags=["serious"]) resolver.smash( sealException(userError(u"Vat ran out of checkpoints"))) except Ejecting: self.log(u"Ejector tried to escape vat turn boundary", tags=["serious"]) resolver.smash( sealException( userError(u"Ejector tried to escape from vat")))