def recv(self, atom, args): if atom is RUN_1: return IntObject(int(unwrapStr(args[0]).encode('utf-8'))) if atom is RUN_2: inp = unwrapStr(args[0]) radix = unwrapInt(args[1]) try: v = int(inp.encode("utf-8"), radix) except ValueError: raise userError(u"Invalid literal for base %d: %s" % (radix, inp)) return IntObject(v) if atom is FROMBYTES_1: return IntObject(int(unwrapBytes(args[0]))) if atom is FROMBYTES_2: bs = unwrapBytes(args[0]) radix = unwrapInt(args[1]) try: v = int(bs, radix) except ValueError: raise userError(u"Invalid literal for base %d: %s" % (radix, bytesToString(bs))) return IntObject(v) raise Refused(self, atom, args)
def run(self, executable, argv, env, stdinFount=None, stdoutDrain=None, stderrDrain=None, stdin=False, stdout=False, stderr=False): # Sixth incarnation: Now with streamcaps! # Unwrap argv. l = [] for arg in argv: bs = unwrapBytes(arg) assert bs is not None, "proven impossible" l.append(bs) argv = l # Unwrap and prep environment. d = {} for (k, v) in env.items(): d[unwrapBytes(k)] = unwrapBytes(v) packedEnv = [k + '=' + v for (k, v) in d.items()] env = d vat = currentVat.get() # Set up the list of streams and attach streamcaps. stdinSink = nullSink stdoutSource = stderrSource = emptySource streams = [] if stdin: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) wrapped = ruv.wrapStream(stream, 1) stdinSink = StreamSink(wrapped, vat) else: streams.append(nullptr(ruv.stream_t)) if stdout: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) wrapped = ruv.wrapStream(stream, 1) stdoutSource = StreamSource(wrapped, vat) else: streams.append(nullptr(ruv.stream_t)) if stderr: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) wrapped = ruv.wrapStream(stream, 1) stderrSource = StreamSource(wrapped, vat) else: streams.append(nullptr(ruv.stream_t)) try: process = ruv.allocProcess() sub = SubProcess(vat, process, argv, env, stdin=stdinSink, stdout=stdoutSource, stderr=stderrSource) vat.enqueueEvent(SpawnProcessIOEvent( vat, sub, process, executable, argv, packedEnv, streams)) return sub except ruv.UVError as uve: raise userError(u"makeProcess: Couldn't spawn process: %s" % uve.repr().decode("utf-8"))
def makeProcess(executable, args, environment): """ Create a subordinate process on the current node from the given executable, arguments, and environment. """ # Third incarnation: libuv-powered and requiring bytes. executable = unwrapBytes(executable) # This could be an LC, but doing it this way fixes the RPython annotation # for the list to be non-None. argv = [] for arg in unwrapList(args): s = unwrapBytes(arg) assert s is not None, "proven impossible by hand" argv.append(s) env = {} for (k, v) in unwrapMap(environment).items(): env[unwrapBytes(k)] = unwrapBytes(v) packedEnv = [k + '=' + v for (k, v) in env.items()] vat = currentVat.get() try: process = ruv.allocProcess() sub = SubProcess(vat, process, argv, env) ruv.spawn(vat.uv_loop, process, file=executable, args=argv, env=packedEnv) sub.retrievePID() return sub except ruv.UVError as uve: raise userError(u"makeProcess: Couldn't spawn process: %s" % uve.repr().decode("utf-8"))
def recv(self, atom, args): if atom is RUN_1: return IntObject(int(unwrapStr(args[0]).encode('utf-8'))) if atom is RUN_2: inp = unwrapStr(args[0]) radix = unwrapInt(args[1]) try: v = int(inp.encode("utf-8"), radix) except ValueError: raise userError(u"Invalid literal for base %d: %s" % ( radix, inp)) return IntObject(v) if atom is FROMBYTES_1: return IntObject(int(unwrapBytes(args[0]))) if atom is FROMBYTES_2: bs = unwrapBytes(args[0]) radix = unwrapInt(args[1]) try: v = int(bs, radix) except ValueError: raise userError(u"Invalid literal for base %d: %s" % ( radix, bytesToString(bs))) return IntObject(v) raise Refused(self, atom, args)
def getAddrInfo(node, service): node = unwrapBytes(node) service = unwrapBytes(service) vat = currentVat.get() gai = ruv.alloc_gai() p, r = makePromise() ruv.stashGAI(gai, (vat, r)) ruv.getAddrInfo(vat.uv_loop, gai, gaiCB, node, service, nullptr(ruv.s.addrinfo)) return p
def getAddrInfo(node, service): node = unwrapBytes(node) service = unwrapBytes(service) vat = currentVat.get() p, r = makePromise() emptyAI = nullptr(ruv.s.addrinfo) with io: ai = emptyAI try: ai = ruv.magic_getAddrInfo(vat, node, service) except object as err: smash(r, StrObject(u"libuv error: %s" % err)) else: resolve(r, wrapList(walkAI(ai)[:])) return p
def makeTCP4ClientEndpoint(host, port): """ Make a TCPv4 client endpoint. """ host = unwrapBytes(host) port = unwrapInt(port) return TCP4ClientEndpoint(host, port)
def evalToPair(self, bs, scope, inRepl=False): ast = realLoad(unwrapBytes(bs)) if inRepl is None: inRepl = False else: inRepl = unwrapBool(inRepl) result, envMap = astEvalToPair(ast, scope, inRepl) return [result, envMap]
def recv(self, atom, args): if atom is SEAL_1: message = unwrapBytes(args[0]) nonce = rsodium.freshNonce() cipher = rsodium.boxSeal(message, nonce, self.publicKey, self.secretKey) return ConstList([BytesObject(cipher), BytesObject(nonce)]) if atom is UNSEAL_2: cipher = unwrapBytes(args[0]) nonce = unwrapBytes(args[1]) try: message = rsodium.boxUnseal(cipher, nonce, self.publicKey, self.secretKey) except rsodium.SodiumError: raise userError(u"unseal/2: Couldn't open this box") return BytesObject(message) raise Refused(self, atom, args)
def moduleFromString(source, recorder): source = unwrapBytes(source) # *Do* catch this particular exception, as it is not a # UserException and thus will kill the process (!!!) if allowed to # propagate. ~ C. assert isinstance(source, bytes) mod = AstModule(recorder, u"<eval>") mod.load(source) return mod
def moduleFromString(source, recorder): source = unwrapBytes(source) # *Do* catch this particular exception, as it is not a # UserException and thus will kill the process (!!!) if allowed to # propagate. ~ C. try: code, topLocals = obtainModuleFromSource(source, recorder, u"<eval>") except LoadFailed: raise userError(u"Couldn't load invalid AST") return code, topLocals
def recv(self, atom, args): if atom is GETCONTENTS_0: return self.open(openGetContentsCB, flags=os.O_RDONLY, mode=0000) if atom is SETCONTENTS_1: data = unwrapBytes(args[0]) sibling = self.temporarySibling(".setContents") p, r = makePromise() vat = currentVat.get() uv_loop = vat.uv_loop fs = ruv.alloc_fs() path = sibling.asBytes() # Use CREAT | EXCL to cause a failure if the temporary file # already exists. flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL sc = SetContents(vat, data, r, sibling, self) ruv.stashFS(fs, (vat, sc)) ruv.fsOpen(uv_loop, fs, path, flags, 0777, openSetContentsCB) return p if atom is OPENFOUNT_0: return self.open(openFountCB, flags=os.O_RDONLY, mode=0000) if atom is OPENDRAIN_0: # Create the file if it doesn't yet exist, and truncate it if it # does. Trust the umask to be reasonable for now. flags = os.O_CREAT | os.O_WRONLY # XXX this behavior should be configurable via namedarg? flags |= os.O_TRUNC return self.open(openDrainCB, flags=flags, mode=0777) if atom is RENAME_1: fr = args[0] if not isinstance(fr, FileResource): raise userError(u"rename/1: Must be file resource") return self.rename(fr.asBytes()) if atom is SIBLING_1: name = unwrapStr(args[0]) if u'/' in name: raise userError(u"sibling/1: Illegal file name '%s'" % name) return self.sibling(name.encode("utf-8")) if atom is TEMPORARYSIBLING_0: return self.temporarySibling(".new") raise Refused(self, atom, args)
def recv(self, atom, args): if atom is FROMPUBLICBYTES_1: publicKey = unwrapBytes(args[0]) expectedSize = intmask(rsodium.cryptoBoxPublickeybytes()) if len(publicKey) != expectedSize: message = u"Expected key length of %d bytes, not %d" % ( expectedSize, len(publicKey)) raise userError(message) return PublicKey(publicKey) if atom is FROMSECRETBYTES_1: secretKey = unwrapBytes(args[0]) expectedSize = intmask(rsodium.cryptoBoxSecretkeybytes()) if len(secretKey) != expectedSize: message = u"Expected key length of %d bytes, not %d" % ( expectedSize, len(secretKey)) raise userError(message) return SecretKey(secretKey) if atom is RUN_0: public, secret = rsodium.freshKeypair() return ConstList([PublicKey(public), SecretKey(secret)]) raise Refused(self, atom, args)
def recv(self, atom, args): if atom is FLOWINGFROM_1: return self if atom is RECEIVE_1: if self._closed: raise userError(u"Can't send data to a closed stream!") if args[0] is NullObject: # Pump-style notification that we're supposed to close. self.flush() self.cleanup() return NullObject # XXX we are punting completely on any notion of backpressure for # now. How to fix: # * Figure out how to get libuv to signal that a write is likely # to complete data = unwrapBytes(args[0]) uv_write = ruv.alloc_write() with ruv.scopedBufs([data]) as bufs: ruv.write(uv_write, self.stream, bufs, 1, writeCB) return NullObject if atom is FLOWABORTED_1: self.cleanup() return NullObject if atom is FLOWSTOPPED_1: # XXX flush() is currently a no-op, but that's not right for the # case where there's pending data. self.flush() self.cleanup() return NullObject if atom is FLUSH_0: self.flush() return NullObject raise Refused(self, atom, args)
def recv(self, atom, args): if atom is FLOWINGFROM_1: self.fount = args[0] return self if atom is RECEIVE_1: data = unwrapBytes(args[0]) self.receive(data) return NullObject if atom is FLOWSTOPPED_1: # Prepare to shut down. Switch to CLOSING to stop future data from # being queued. self.closing() return NullObject if atom is FLOWABORTED_1: # We'll shut down cleanly, but we're going to discard all the work # that we haven't yet written. self.bufs = [] self.closing() return NullObject raise Refused(self, atom, args)
def run(self, executable, argv, env, stdinFount=None, stdoutDrain=None, stderrDrain=None, stdin=False, stdout=False, stderr=False): # Sixth incarnation: Now with streamcaps! # Unwrap argv. l = [] for arg in argv: bs = unwrapBytes(arg) assert bs is not None, "proven impossible" l.append(bs) argv = l # Unwrap and prep environment. d = {} for (k, v) in env.items(): d[unwrapBytes(k)] = unwrapBytes(v) packedEnv = [k + '=' + v for (k, v) in d.items()] env = d vat = currentVat.get() # Set up the list of streams and attach streamcaps. stdinSink = nullSink stdoutSource = stderrSource = emptySource streams = [] if stdin: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) wrapped = ruv.wrapStream(stream, 1) stdinSink = StreamSink(wrapped, vat) else: streams.append(nullptr(ruv.stream_t)) if stdout: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) wrapped = ruv.wrapStream(stream, 1) stdoutSource = StreamSource(wrapped, vat) else: streams.append(nullptr(ruv.stream_t)) if stderr: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) wrapped = ruv.wrapStream(stream, 1) stderrSource = StreamSource(wrapped, vat) else: streams.append(nullptr(ruv.stream_t)) try: process = ruv.allocProcess() sub = SubProcess(vat, process, argv, env, stdin=stdinSink, stdout=stdoutSource, stderr=stderrSource) ruv.spawn(vat.uv_loop, process, file=executable, args=argv, env=packedEnv, streams=streams) sub.retrievePID() return sub except ruv.UVError as uve: raise userError(u"makeProcess: Couldn't spawn process: %s" % uve.repr().decode("utf-8"))
def loadMAST(bs): return BuildKernelNodes().visitExpr(realLoad(unwrapBytes(bs)))
def evalToPair(self, bs, scope, inRepl=False): ast = realLoad(unwrapBytes(bs)) result, envMap = astEvalToPair(ast, scope, u"<eval>", inRepl) return [result, envMap]
def run(self, bs, scope): ast = realLoad(unwrapBytes(bs)) return astEvalToPair(ast, scope, u"<eval>")[0]
def recvNamed(self, atom, args, namedArgs): if atom is RUN_3: # Fourth incarnation: Now with stdio hookups. executable = unwrapBytes(args[0]) # This could be an LC, but doing it this way fixes the RPython annotation # for the list to be non-None. argv = [] for arg in unwrapList(args[1]): s = unwrapBytes(arg) assert s is not None, "proven impossible by hand" argv.append(s) env = {} for (k, v) in unwrapMap(args[2]).items(): env[unwrapBytes(k)] = unwrapBytes(v) packedEnv = [k + '=' + v for (k, v) in env.items()] vat = currentVat.get() # Set up the list of streams. Note that, due to (not incorrect) # libuv behavior, we must wait for the subprocess to be spawned # before we can interact with the pipes that we are creating; to # do this, we'll have a list of the (f, d) pairs that we need to # start, and we'll ensure that that doesn't happen until after the # process has spawned. streams = [] fount = namedArgs.extractStringKey(u"stdinFount", None) if fount is None: streams.append(nullptr(ruv.stream_t)) else: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) drain = StreamDrain(stream, vat) vat.sendOnly(fount, FLOWTO_1, [drain], EMPTY_MAP) for name in [u"stdoutDrain", u"stderrDrain"]: drain = namedArgs.extractStringKey(name, None) if drain is None: streams.append(nullptr(ruv.stream_t)) else: stream = ruv.rffi.cast(ruv.stream_tp, ruv.alloc_pipe(vat.uv_loop)) streams.append(stream) fount = StreamFount(stream, vat) vat.sendOnly(fount, FLOWTO_1, [drain], EMPTY_MAP) try: process = ruv.allocProcess() sub = SubProcess(vat, process, argv, env) ruv.spawn(vat.uv_loop, process, file=executable, args=argv, env=packedEnv, streams=streams) sub.retrievePID() return sub except ruv.UVError as uve: raise userError(u"makeProcess: Couldn't spawn process: %s" % uve.repr().decode("utf-8")) val = self.mirandaMethods(atom, args, namedArgs) if val is None: raise Refused(self, atom, args) else: return val