0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

feat(std/wasi): add return on exit option (#8605)

This adds an exitOnReturn option to context making it 
possible to unwind the stack on the exit(2) syscall 
instead of delegating to it directly.

Use case is being able to treat WASI execution contexts 
as children that don't kill the parent on exit.
This commit is contained in:
Casper Beyer 2020-12-04 02:57:35 +08:00 committed by GitHub
parent de036e1f08
commit 0ea1c6f5b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 3 deletions

View file

@ -207,6 +207,10 @@ function syscall<T extends CallableFunction>(target: T) {
try {
return target(...args);
} catch (err) {
if (err instanceof ExitStatus) {
throw err;
}
switch (err.name) {
case "NotFound":
return ERRNO_NOENT;
@ -266,15 +270,25 @@ interface FileDescriptor {
entries?: Deno.DirEntry[];
}
export class ExitStatus {
code: number;
constructor(code: number) {
this.code = code;
}
}
export interface ContextOptions {
args?: string[];
env?: { [key: string]: string | undefined };
preopens?: { [key: string]: string };
exitOnReturn?: boolean;
}
export default class Context {
args: string[];
env: { [key: string]: string | undefined };
exitOnReturn: boolean;
memory: WebAssembly.Memory;
fds: FileDescriptor[];
@ -284,6 +298,7 @@ export default class Context {
constructor(options: ContextOptions) {
this.args = options.args ? options.args : [];
this.env = options.env ? options.env : {};
this.exitOnReturn = options.exitOnReturn ?? true;
this.memory = null!;
this.fds = [
@ -1497,7 +1512,11 @@ export default class Context {
"proc_exit": syscall((
rval: number,
): never => {
Deno.exit(rval);
if (this.exitOnReturn) {
Deno.exit(rval);
}
throw new ExitStatus(rval);
}),
"proc_raise": syscall((

View file

@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
import Context from "./snapshot_preview1.ts";
import { assertEquals, assertThrows } from "../testing/asserts.ts";
import Context, { ExitStatus } from "./snapshot_preview1.ts";
import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";
import { copy } from "../fs/mod.ts";
import * as path from "../path/mod.ts";
@ -179,6 +179,24 @@ Deno.test("context_start", function () {
TypeError,
"export _start must be a function",
);
try {
const context = new Context({
exitOnReturn: false,
});
context.start({
exports: {
_start() {
const exit = context.exports["proc_exit"] as CallableFunction;
exit(0);
},
memory: new WebAssembly.Memory({ initial: 1 }),
},
});
} catch (err) {
assert(err instanceof ExitStatus);
assertEquals(err.code, 0);
}
});
Deno.test("context_initialize", function () {