Giter Club home page Giter Club logo

isolated-vm's People

Contributors

alufers avatar artch avatar augjoh avatar davidjb avatar ferjakub avatar fpedrei avatar gramthanos avatar idleman avatar isker avatar jeromegn avatar jerska avatar johnkmzhou avatar kiddkai avatar koto avatar laverdet avatar marcrock22 avatar mareklibra avatar mwpenny avatar orgads avatar pavlokolodka avatar rs avatar s-diez avatar seanet7or avatar shiftinv avatar spencersharkey avatar vitamindck avatar y-exp avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

isolated-vm's Issues

Segfault during "isolate environment executor unlock"

Just ran into this segfault (again, under some load, but limiting context creation to 1 at a time.)

PID 96350 received SIGSEGV for address: 0x20
0   segfault-handler.node               0x0000000105c44168 _ZL16segfault_handleriP9__siginfoPv + 280
1   libsystem_platform.dylib            0x00007fffe68deb3a _sigtramp + 26
2   ???                                 0x00007000048bd888 0x0 + 123145378584712
3   isolated_vm.node                    0x0000000104b84b60 _ZN3ivm18IsolateEnvironment8Executor6UnlockD1Ev + 32
4   isolated_vm.node                    0x0000000104b93864 _ZN3ivm14ThreePhaseTask7RunSyncERNS_13IsolateHolderEb + 436
5   isolated_vm.node                    0x0000000104bc494f _ZN3ivm14ThreePhaseTask3RunILi4ENS_11ApplyRunnerEJRNS_15ReferenceHandleERN2v810MaybeLocalINS5_5ValueEEERNS6_INS5_5ArrayEEERNS6_INS5_6ObjectEEERNSt3__110shared_ptrINS_12RemoteHandleINS5_7ContextEEEEERNSH_INSI_IS7_EEEEEEENS5_5LocalIS7_EERNS_13IsolateHolderEDpOT1_ + 175
6   isolated_vm.node                    0x0000000104bc4a47 _ZN3ivm14FunctorRunners11RunCallbackIZNS_11ClassHandle17ParameterizeEntryILin1EPFN2v85LocalINS4_5ValueEEEPNS_15ReferenceHandleENS4_10MaybeLocalIS6_EENSA_INS4_5ArrayEEENSA_INS4_6ObjectEEEEXadL_ZNS2_10MethodCastIMS8_FS7_SB_SD_SF_EE6InvokeIXadL_ZNS8_5ApplyILi4EEES7_SB_SD_SF_EEEES7_S9_SB_SD_SF_EEEEvRKNS4_20FunctionCallbackInfoIS6_EEEUlvE_SQ_EEvRT0_T_ + 135
7   node                                0x00000001001f9260 _ZN2v88internal25FunctionCallbackArguments4CallEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEE + 416
8   node                                0x0000000100261580 _ZN2v88internal12_GLOBAL__N_119HandleApiCallHelperILb0EEENS0_11MaybeHandleINS0_6ObjectEEEPNS0_7IsolateENS0_6HandleINS0_10HeapObjectEEESA_NS8_INS0_20FunctionTemplateInfoEEENS8_IS4_EENS0_16BuiltinArgumentsE + 800
9   node                                0x0000000100260be3 _ZN2v88internalL26Builtin_Impl_HandleApiCallENS0_16BuiltinArgumentsEPNS0_7IsolateE + 259
10  ???                                 0x00003a1fc788463d 0x0 + 63908165994045
11  ???                                 0x00003a1fc79742ea 0x0 + 63908166976234
libc++abi.dylib: terminating

I tried with the latest master (at the time of this writing: 242e864 too. I'm using node 8.9.4 from your tailcall-backport branch.

Handling unhandled promise rejections

Is an event like browsers' unhandledrejection or node's unhandledRejection possible with V8?

It looks like the docs for RunMicroTasks says any errors are swallowed. I can't quite tell how browsers or node.js do it though.

CPU Usage

Would it be possible to get user/system and internal/external CPU usage for code ran into an isolate?

More states getters

The addition of isDisposed helps a lot. Is that also set while it is being disposed of?

It seems like surfacing a few more states would help predicting the lifecycle of isolates and contexts.

It'd be useful to be able to tell when an isolate is being disposed of, maybe isDisposing? I suspect there are other states to the isolate. Is creating an isolate really synchronous?

Contexts also have a few states. While they're being created, while they're being released and when they're actually released.

How to make transferable values from NativeModule?

(Hopefully this is not too much, there's no rush in responding to any of our issues!)

I'm excited by the prospect of the native module work you've done. I think it will help a lot with our project at Fly.

I was wondering what makes a value transferable exactly? I'd be interested in making constructs that can be used both in the node isolate and plain v8 isolates.

For instance, a ReadableStream implementation would allow reading from a source natively, both in nodejs and v8 isolates. If the underlying stream is managed outside of both node and v8, then I imagine it should be usable by either isolate. Of course it would be locked to a single reader at a time (and won't be readable after the first read, like the spec prescribes.)

Our idea is to allow for passing ReadableStream created in either nodejs or v8, back and forth. Reading from it would not involve calling back into the other isolate.

Is this something in the realm of possibilities?

New crash with latest 1.5.1

I think this is new, here's 2 core dumps:

[Current thread is 1 (Thread 0x7fb07c846700 (LWP 38))]
(gdb) where
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1  0x00007fb0986b242a in __GI_abort () at abort.c:89
#2  0x00007fb0991e60ad in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007fb0991e4066 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007fb0991e40b1 in std::terminate() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007fb0991e42c9 in __cxa_throw () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007fb09920cf3e in std::__throw_system_error(int) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007fb09920f0e8 in std::thread::join() () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#8  0x00007fb096417b0c in thread_pool_t::resize (size=0, this=0x7fb096679640 <ivm::IsolateEnvironment::Scheduler::thread_pool>) at ../src/isolate/../thread_pool.h:130
#9  thread_pool_t::~thread_pool_t (this=0x7fb096679640 <ivm::IsolateEnvironment::Scheduler::thread_pool>, __in_chrg=<optimized out>) at ../src/isolate/../thread_pool.h:64
#10 0x00007fb0986b3940 in __run_exit_handlers (status=-1, listp=0x7fb098a175d8 <__exit_funcs>, run_list_atexit=run_list_atexit@entry=true, run_dtors=run_dtors@entry=true) at exit.c:83
#11 0x00007fb0986b399a in __GI_exit (status=<optimized out>) at exit.c:105
#12 0x00007fb084368a7b in segfault_handler(int, siginfo_t*, void*) () from /usr/src/app/node_modules/segfault-handler/build/Release/segfault-handler.node
#13 <signal handler called>
#14 __memmove_avx_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:286
#15 0x00005619306feb57 in v8::internal::JSTypedArray::MaterializeArrayBuffer(v8::internal::Handle<v8::internal::JSTypedArray>) ()
#16 0x00005619306fee80 in v8::internal::JSTypedArray::GetBuffer() ()
#17 0x00005619308ca73f in v8::internal::Runtime_TypedArrayGetBuffer(int, v8::internal::Object**, v8::internal::Isolate*) ()

... + around 120 lines of ??

and

[Current thread is 1 (Thread 0x7fb82e99eb80 (LWP 13))]
(gdb) where
#0  0x00007fb82d559317 in kill () at ../sysdeps/unix/syscall-template.S:84
#1  0x0000558c28bef669 in uv_kill (pid=<optimized out>, signum=<optimized out>) at ../deps/uv/src/unix/process.c:579
#2  0x0000558c289ab154 in node::Kill(v8::FunctionCallbackInfo<v8::Value> const&) ()
#3  0x0000558c281d92a8 in v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) ()
#4  0x0000558c282491ff in v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) ()
#5  0x0000558c28249a89 in v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) ()

... + around 40 lines of ??

Assertion failed for null pointer

From time to time, I get

node: ../src/platform_delegate.h:45: virtual void ivm::PlatformDelegate::CallOnForegroundThread(v8::Isolate*, v8::Task*): Assertion `s_isolate != nullptr' failed.

While running our specs on travis. I have not seen that locally. It's not happening consistently on travis either (we have some succeeding builds with the same code.)

It seems to happen at the same spot every time. Which is strange. It's not a particularly special scenario.

I'm sure this is due to some weird logic in our code, like a race condition, but I would expect isolated-vm to fail in a catchable way. Now it just crashes the process.

You can see relevant logs here: https://travis-ci.org/superfly/fly/builds/333482078 you can run the https://github.com/superfly/fly specs with npm test if you want to try and reproduce it.

How to catch compilation errors with createSnapshot

I can't find a way to catch errors thrown during snapshot creation:

const ivm = require("isolated-vm");

try {
    const snapshot = ivm.Isolate.createSnapshot([{code: '**'}]);
    const isolate = new ivm.Isolate({ snapshot });
} catch (e) {
    console.log('Caught', e);
}

Output:

<isolated-vm>:0: Uncaught SyntaxError: Unexpected token **

Expected output:

Caught SyntaxError: Unexpected token **

minor errors installing fresh clone

This is a great project, looking forward to trying out. When running npm run install on a fresh clone I got two errors in compilation:

../src/isolate/../external_copy.h:123:37: error: no member named 'free' in namespace 'std'; did you mean simply 'free'?

and

../src/isolate/class_handle.h:23:27: error: unknown type name 'nullptr_t'; did you mean 'std::nullptr_t'

After making these two changes it compiled great and npm test passes the test suite:

  • adding #include <stdlib> to external_copy.h.
  • changing nullptr_t to std::nullptr_t in class_handle.h:23:27

It might be possible that these be just compiler version issues instead. I tried clang and gcc-7.

Catch async uncaught exceptions

Would it be possible to catch async uncaught exception on a per context basis?

const ivm = require('isolated-vm');
const isolate = new ivm.Isolate();
const context = isolate.createContextSync();
const jail = context.globalReference();

jail.setSync('asyncException', new ivm.Reference(() => {
    setTimeout(() => {throw new Error()}, 1000);
}));

const script = isolate.compileScriptSync('asyncException.apply()');

script.run(context).catch((e) => {
    // Won't catch async exception, would be nice to be able to wait for
    // all scheduled events and capture their exceptions if any.
});

Assertion failed: (try_catch.HasCaught())

Another assertion failure.

Assertion failed: (try_catch.HasCaught()), function operator(), file ../src/shareable_isolate.h, line 776.

I was able to get there running this code:

const ivm = require('isolated-vm')

const iso = new ivm.Isolate();

(async function () {
  let i = 0
  while (true) {
    console.log("iteration", i)
    await iso.createContext()
    i++
  }
})()

Wouldn't it be better to not use those assertions? They appear to crash the process entirely. Couldn't they just throw some errors that could be caught in node?

Segfault regarding TypedArrays

I got this while playing with probably-too-large ArrayBuffer allocations:

PID 23911 received SIGSEGV for address: 0x0
0   segfault-handler.node               0x00000001038f3168 _ZL16segfault_handleriP9__siginfoPv + 280
1   libsystem_platform.dylib            0x00007fffe68deb3a _sigtramp + 26
2   ???                                 0x0000000105950600 0x0 + 4388619776
3   node                                0x0000000100559129 _ZN2v88internal12JSTypedArray22MaterializeArrayBufferENS0_6HandleIS1_EE + 601
4   node                                0x000000010068a562 _ZN2v88internal27Runtime_TypedArrayGetBufferEiPPNS0_6ObjectEPNS0_7IsolateE + 70
5   ???                                 0x0000141d30846eb8 0x0 + 22115600592568

I couldn't find the exact cause of this, I worked around the issue another way. In the past you've been able to fix segfaults from these traces without much context, so maybe you can do the same this time :)

Best way to pass object with Reference

What's the best way to pass objects to isolate that contain Reference.

const ivm = require('isolated-vm');
const isolate = new ivm.Isolate({ memoryLimit: 128 });

const context = isolate.createContextSync();
const globalReference = context.globalReference();

const obj = {
  a: 1,
  b: 2,
  c: new ivm.Reference(function() {})
}

globalReference.setSync('obj', new ivm.ExternalCopy(obj).copyInto());

let r = isolate.compileScriptSync('obj.a + obj.b').runSync(context);
console.log(r);

This gives an error:

#<Reference> could not be cloned.

As I understand Reference can't be passed to ExternalCopy. What's the best way to transfer objects that contain functions?

Used somewhere in production?

This is a very interesting project. Is this used somewhere in production or it is still at the experimention stage?

Async operations are clogging the loop?

I've been using isolated-vm to process a stream with custom JS functions which I run within a V8 instance, but I'm encountering sluggishness in places.

It goes something like:

  • get a Readable stream
  • create a Transform stream which passes the input to a function running within the isolated vm
  • wait for callback to be called with desired output
  • push into the stream
  • call the Transform callback
const tr = new Transform({
  transform(chunk, encoding, callback) {
    someIsolatedFunction.apply(null, [chunk.toString(), new ivm.Reference(function(err, newChunk){
      // error checking
      tr.push(newChunk)
      callback()
    }]
})

src.pipe(tr).pipe(dst)

There is major slowness if I don't use a setTimeout(fn, 0) or setImmediate(fn) for the callback().

This is only an example, I've noticed that in many places.

I run everything using the async functions provided by isolated-vm. Everything works great except for slowness that can reach up to 1-5 seconds (during which nothing is happening.)

I'm sure I'm missing something or doing something incorrectly. If this is normal and I should pepper my code with setImmediate, that's ok with me, but I'm not sure where to put them.

Zero-Copy references between Isolates

I would like to use isolate-vm's multi-threading capabilities to implement parallel sort and scan algorithms, but the copy-in/out requirements add time and space complexity on the order of number of threads.

Are inter-isolate references possible with caveats? isolated-vm enforces reasonable caveats about parallel access to shared resources (i.e.: I/O), might it be possible to implement zero-copy inter-isolate references with caveats (i.e.: read-only, persistent data)?

Wait for events

Is there a way to get a promise that would resolve when all events scheduled by the context are done?

Releases and versioning

Would it be possible to make releases more frequently? I tend to have to use the github source in my npm package to benefit from the latest features.

What versioning scheme does isolated-vm adhere to?

There were a lot of features added lately, but I've only seen patch version bumps.

I find changelogs painstaking to maintain, we've started using the standard-version npm package for this. As long as the commits follow the Conventional Commits format, it'll automatically decide how to bump the version.

TypedArray segfault

I've noticed this when running with an inspector instance:

PID 92654 received SIGSEGV for address: 0x0
0   segfault-handler.node               0x000000010723f168 _ZL16segfault_handleriP9__siginfoPv + 280
1   libsystem_platform.dylib            0x00007fffe68deb3a _sigtramp + 26
2   ???                                 0x4187c18000000000 0x0 + 4721955489821229056
3   node                                0x0000000100540055 _ZN2v88internal12JSTypedArray22MaterializeArrayBufferENS0_6HandleIS1_EE + 601
4   node                                0x000000010066ebee _ZN2v88internal27Runtime_TypedArrayGetBufferEiPPNS0_6ObjectEPNS0_7IsolateE + 70
5   ???                                 0x0000230eefea3c58 0x0 + 38547061619800
6   ???                                 0x0000230eeff7a529 0x0 + 38547062498601
libc++abi.dylib: terminating
[1]    92654 abort      LOG_LEVEL=info ../../superfly/fly/bin/fly server --inspect

Seems to only happen if I take a heap snapshot and then run a lot of requests concurrently (but they're queued one at a time via a mutex.)

Not sure if relevant to anything.

transfer: true used on copy() or copyInto() does not work as documented

According to the readme, it's possible to use {transfer: true} during .copy() and .copyInto(), but with a simple test case I was unable to make this pass.

const ivm = require('isolated-vm')
const iso = new ivm.Isolate()
const toArrayBuffer = require('to-arraybuffer')

const ctx = iso.createContextSync()

let arrBuf = toArrayBuffer(Buffer.from("string"))
console.log("before", Buffer.from(arrBuf))

let g = ctx.globalReference()
g.setSync("blah", new ivm.ExternalCopy(arrBuf).copyInto({ transfer: true }))

console.log("after", Buffer.from(arrBuf))

This outputs:

$ node test.js
before <Buffer 73 74 72 69 6e 67>
after <Buffer 73 74 72 69 6e 67>

If I move the transfer option to the constructor call, it does work:

$ node test.js
before <Buffer 73 74 72 69 6e 67>
after <Buffer >

Maybe I misunderstood the documentation though.

Script run (async) does not reject the promise on error

The timeout on Script.run seems to interrupt the execution but does not reject the returned promise.

Same with exceptions thrown in unchained promises:

const ivm = require("isolated-vm");

function runSync() {
	const isolate = new ivm.Isolate();
	const context = isolate.createContextSync();
	const script = isolate.compileScriptSync('new Promise(() => {throw new Error("some error")})');

	try {
		script.runSync(context);
		console.log('sync not caught');
	} catch (e) {
		console.log('sync caught', e);
	}
}



async function runAsync() {
	const isolate = new ivm.Isolate();
	const context = await isolate.createContext();
	const script = await isolate.compileScript('new Promise(() => {throw new Error("some error")})');

	try {
		await script.run(context);
		console.log('async not caught');
	} catch (e) {
		console.log('async caught', e);
	}
}

runSync();
runAsync();

Output:

sync caught Error: some error
    at runSync (โ€ฆ:9:10)
    at Object.<anonymous> (โ€ฆ:31:1)
    at Module._compile (module.js:624:30)
    at Object.Module._extensions..js (module.js:635:10)
    at Module.load (module.js:545:32)
    at tryModuleLoad (module.js:508:12)
    at Function.Module._load (module.js:500:3)
    at Function.Module.runMain (module.js:665:10)
    at startup (bootstrap_node.js:187:16)
    at bootstrap_node.js:608:3
async not caught

ivm somehow changes between context

Hey Marcel,

I found this weird behaviour where contexts will have a different ivm (initially set globally) in subsequent runs.

I'm not sure how to explain this better, I have a test case:

const ivm = require('isolated-vm');

const iso = new ivm.Isolate()
const script = `function test(arg1){
  return arg1 instanceof ivm.Reference
}`

async function makeContext() {
  const ctx = await iso.createContext()

  const g = await ctx.globalReference()
  await g.set("ivm", ivm)

  const s = await iso.compileScript(script)
  await s.run(ctx)

  const fn = await g.get("test")
  console.log(await fn.apply(null, [new ivm.Reference(function () { })]))
}

makeContext()
makeContext()

This outputs:

true
false

Am I doing something wrong? I would expect the returned value to be true all the time.

Snapshot Isolate

I would like to create snapshots of already created isolates.
This can be useful if the isolate contains a state that can be modified with the exposed functions and which should be reused at repeated execution.

Execution fails with debugger attached

NodeJS: 8.9.4
isolate-vm: 1.0.0

Every time I try to execute script with attached debugger, I get the following:

/usr/bin/node[743]: ../src/node.cc:1456:void node::InternalCallbackScope::Close(): Assertion `(env_->execution_async_id()) == (0)' failed.
 1: node::Abort() [/usr/bin/node]
 2: 0x121a6bb [/usr/bin/node]
 3: 0x121eaf6 [/usr/bin/node]
 4: node::NodePlatform::FlushForegroundTasksInternal() [/usr/bin/node]
 5: node::inspector::NodeInspectorClient::runMessageLoopOnPause(int) [/usr/bin/node]
 6: v8_inspector::V8Debugger::handleProgramBreak(v8::Local<v8::Context>, v8::Local<v8::Object>, v8::Local<v8::Value>, v8::Local<v8::Array>, bool, bool) [/usr/bin/node]
 7: v8_inspector::V8Debugger::BreakProgramRequested(v8::Local<v8::Context>, v8::Local<v8::Object>, v8::Local<v8::Value>) [/usr/bin/node]
 8: v8::internal::Debug::OnDebugBreak(v8::internal::Handle<v8::internal::Object>) [/usr/bin/node]
 9: v8::internal::Debug::Break(v8::internal::JavaScriptFrame*) [/usr/bin/node]
10: v8::internal::Runtime_DebugBreakOnBytecode(int, v8::internal::Object**, v8::internal::Isolate*) [/usr/bin/node]
11: 0x104ca98463d

Here is my code:

async function executeScript(type, data, code) {
    console.time('Exec');

    let result = null;
    let error = null;

    const compiledScript = compiledScripts.get(type);

    if (compiledScript) {
        let globalContext = await isolate.createContext({ inspector: true });
        let globalRef = globalContext.globalReference();

        await globalRef.set('__code', code);
        await globalRef.set('__data', JSON.stringify(data));

        try {
            result = await compiledScript.run(globalContext, runOptions);
        } catch (e) {
            error = e;
        }

        // Reset values
        await globalRef.set('__code', null);
        await globalRef.set('__data', null);

        globalRef.dispose();
        globalContext.release();

        globalRef = null;
        globalContext = null;
    }

    console.timeEnd('Exec');

    if (error) {
        return Promise.reject(error);
    }

    return Promise.resolve(result);
}

Single entrypoint

This is probably caused by some misunderstanding from my side, but I'd like to know how I'd go about providing a single entry point (function) to pass data into my isolate. Since the isolate contains user code, putting data into the global context or declaring a top level named function is not really an option, because the user will be able to call and/or modify the data.

Therefore I've tried the following, wrapped in an IIFE because top level anonymous functions are not allowed.

    const isolate = new ivm.Isolate()
    const context = await isolate.createContext()

    const script = await isolate.compileScript(`
        ;(function() {
            return function() {}
        }())      
    `)

    return await script.run(context)

Unfortunately this returns undefined, since it works with primitives (numbers, strings, null), but not with functions or objects, I assume it has something to do with the value not being transferable.

Could you please explain if I'm missing something here or provide some alternative solution?

Let me know if you need any additonal information regarding my use case.

Is it possible to share node modules?

Hi,

I just read the documentation but all examples compile very simple code which has no state and no link to the host state.

I'm wondering: is it possible to share node modules like puppeteer for instance? If you don't provide access to the fs module for instance, and the library you provided need it, what happens?

In my case, I have a pool of connections to Chrome and I want to inject it in a isolated script. By reading the documentation I'm not very confident that's possible. It seems to me everything shared with an isolate is serialized and thus it only applies to raw data but not stateful objects.

I would love a bit of clarification. Thanks.

Question: How can I import functions? All i keep getting is references...

const go = ($ = {}) => {
    const vm = $.vm || newVM({ memoryLimit: 8 });
    const globals = $.globals || {};
    const ctx = $.context || newContext(vm);
    const gl = globalSetter(ctx);
    Object.keys(globals).forEach(name => {
        const inp = globals[name];
        gl.setSync(`__${name}`, new ivm.Reference(inp));
    });
    // v This one was taken from example v
    gl.setSync("_log", new ivm.Reference(function (...$) {
        console.log(...$);
    }));
    // ^^^^^^^^^^
    let script = $.code || (() => { });
    vm.compileScriptSync(`new ` + script).runSync(ctx);
};

Not even the exampe code worked, it still comes up as a reference.

Timeout does not trigger if something is registered on the event loop

'use strict';
let ivm = require('isolated-vm');

setTimeout(() => {
    console.log('timeout');
}, 1000);

(async function() {
	let isolate = new ivm.Isolate;
	let context = isolate.createContextSync();
	let global = context.globalReference();
	global.setSync('global', global.derefInto());
	isolate.compileScriptSync('global.run = () => { for(;;); }').runSync(context);
	let run = global.getSync('run');
	try {
		run.applySync(undefined, [], { timeout: 20 });
		console.log('what?');
	} catch (err) {}

	try {
		await run.apply(undefined, [], { timeout: 20 });
		console.log('what?');
	} catch (err) {
		console.log('pass');
	}
})().catch(console.error);

Output:

<1 sec>
timeout
pass

Assertion failed: (tasks.empty())

I get the following error sometimes when trying to dispose of an Isolate:

Assertion failed: (tasks.empty()), function Dispose, file ../src/shareable_isolate.h, line 357.

I'm only running one context and am waiting for all the code I'm running to be done before disposing of its isolate.

Anything I should be doing before disposing of my Isolate?

Note: I'm using master.

Transferable values and errors

Is it possible to know beforehand if a value is transferable or not?

It appears:

  • string, number, boolean types are transferable as-is because they're primitives
  • the return value of ExternalCopy(value).copyInto() is transferable where value is anything

Is it possible to detect when a value is transferable? I can check for primitives, but I'm not sure how to tell from a copied ExternalCopy. The TypeScript definition says it returns the assigned type T, but I'm not sure it can be trusted. Even if it did, how would I know it's already been set as transferable?

I've started getting promise rejections when using apply on an ivm.Reference<Function>. I'm wondering if the return value from those functions are passed in. I switched everything to return undefined, but I still get the

A non-transferable value was passed

error if I check .caught() on that promise.

Is it possible this is coming from a different .apply() call? Given this package is 100% C++, it is hard to debug, figure out return values and the general flow of things.

Segfault in Isolate Environment AsyncCallbackPool

I don't have the trace unfortunately. The segfault-handler package doesn't always catch it.

Here's the log line just before the process crashed (exit code 134):

node: ../src/isolate/environment.cc:171: static void ivm::IsolateEnvironment::Scheduler::AsyncCallbackPool(bool, void*): Assertion `root_async.data == nullptr' failed.

This is the only line I could find, this is in production. Our process promptly restarted afterwards.

Segfault v8::SnapshotCreator::CreateBlob

Got a segfault with the following code (see stack trace below):

"use strict";

const ivm = require("isolated-vm");
class Function {
    constructor(code, memoryLimit) {
        const snapshot = ivm.Isolate.createSnapshot([{
                code,
                filename: "handler.js",
            }]);
        this.isolate = new ivm.Isolate({ memoryLimit, snapshot });
    }
    async execute(request, context, callback) {
        try {
            const ctx = await this.isolate.createContext();
            const jail = ctx.globalReference();
            jail.set('$callback', new ivm.Reference((result) => {
                callback(result);
            }));
            const handler = await jail.get('handler');
            const $request = new ivm.ExternalCopy(request).copyInto();
            const $context = new ivm.ExternalCopy(context).copyInto();
            const $callback = new ivm.ExternalCopy((result) => {
                $callback.apply(undefined, [new ivm.ExternalCopy(result).copyInto()]);
            }).copyInto();
            await handler.apply(undefined, [$request, $context, $callback]);
        }
        catch (e) {
            console.error(e);
        }
    }
}

const h = '' + async function handler(request, _, callback) {
    callback({ status: 200, body: 'hello world' });
};
const f = new Function(h);
f.execute({ uri: '/test' }, null, (result) => {
    console.log(result.body);
});
Process:               node [99101]
Path:                  /usr/local/Cellar/node/8.7.0/bin/node
Identifier:            node
Version:               ???
Code Type:             X86-64 (Native)
Parent Process:        zsh [90637]
Responsible:           node [99101]
User ID:               501

Date/Time:             2017-10-22 05:25:39.802 -0700
OS Version:            Mac OS X 10.13 (17A405)
Report Version:        12
Bridge OS Version:     3.0 (14Y661)
Anonymous UUID:        8639B6BE-9E0D-4033-485E-CFA43926FE12

Sleep/Wake UUID:       EA1F9B1B-3999-454B-9BBE-AC8AD38C74FB

Time Awake Since Boot: 290000 seconds
Time Since Wake:       19000 seconds

System Integrity Protection: enabled

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       KERN_INVALID_ADDRESS at 0x0000000000000000
Exception Note:        EXC_CORPSE_NOTIFY

Termination Signal:    Segmentation fault: 11
Termination Reason:    Namespace SIGNAL, Code 0xb
Terminating Process:   exc handler [0]

VM Regions Near 0:
--> 
    __TEXT                 0000000100000000-0000000100e32000 [ 14.2M] r-x/rwx SM=COW  /usr/local/Cellar/node/8.7.0/bin/node

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   node                          	0x00000001001a928d v8::SnapshotCreator::CreateBlob(v8::SnapshotCreator::FunctionCodeHandling) + 671
1   isolated_vm.node              	0x0000000103e8a302 ivm::CreateSnapshot(v8::Local<v8::Array>, v8::MaybeLocal<v8::String>) + 1618
2   isolated_vm.node              	0x0000000103eb504b void ivm::ClassHandle::ParameterizeEntry<0, v8::Local<v8::Value> (*)(v8::Local<v8::Array>, v8::MaybeLocal<v8::String>), &(ivm::CreateSnapshot(v8::Local<v8::Array>, v8::MaybeLocal<v8::String>))>(v8::FunctionCallbackInfo<v8::Value> const&) + 123
3   node                          	0x00000001001d08a4 v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) + 430
4   node                          	0x0000000100219e8b v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::HeapObject>, v8::internal::Handle<v8::internal::FunctionTemplateInfo>, v8::internal::Handle<v8::internal::Object>, v8::internal::BuiltinArguments) + 775
5   node                          	0x00000001002195ae v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) + 259
6   ???                           	0x00000448c268463d 0 + 4710545770045
7   ???                           	0x00000448c27745fc 0 + 4710546753020
8   ???                           	0x00000448c273f9ce 0 + 4710546536910
9   ???                           	0x00000448c2685d1b 0 + 4710545775899
10  ???                           	0x00000448c268573e 0 + 4710545774398
11  ???                           	0x00000448c2775d87 0 + 4710546759047
12  ???                           	0x00000448c273f9ce 0 + 4710546536910
13  ???                           	0x00000448c2774048 0 + 4710546751560
14  ???                           	0x00000448c273f9ce 0 + 4710546536910
15  ???                           	0x00000448c277474a 0 + 4710546753354
16  ???                           	0x00000448c273f9ce 0 + 4710546536910
17  ???                           	0x00000448c277474a 0 + 4710546753354
18  ???                           	0x00000448c273f9ce 0 + 4710546536910
19  ???                           	0x00000448c27745fc 0 + 4710546753020
20  ???                           	0x00000448c273f9ce 0 + 4710546536910
21  ???                           	0x00000448c2775002 0 + 4710546755586
22  ???                           	0x00000448c273f9ce 0 + 4710546536910
23  ???                           	0x00000448c2774048 0 + 4710546751560
24  ???                           	0x00000448c273f9ce 0 + 4710546536910
25  ???                           	0x00000448c2792229 0 + 4710546874921
26  ???                           	0x00000448c273f9ce 0 + 4710546536910
27  ???                           	0x00000448c2774da1 0 + 4710546754977
28  ???                           	0x00000448c273f9ce 0 + 4710546536910
29  ???                           	0x00000448c273e479 0 + 4710546531449
30  ???                           	0x00000448c268410d 0 + 4710545768717
31  node                          	0x00000001004294af v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, bool, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Handle<v8::internal::Object>, v8::internal::Execution::MessageHandling) + 613
32  node                          	0x00000001004291eb v8::internal::(anonymous namespace)::CallInternal(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*, v8::internal::Execution::MessageHandling) + 160
33  node                          	0x00000001001bcf57 v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 307
34  node                          	0x0000000100760e4e node::LoadEnvironment(node::Environment*) + 575
35  node                          	0x0000000100768b07 node::Start(v8::Isolate*, node::IsolateData*, int, char const* const*, int, char const* const*) + 433
36  node                          	0x0000000100762991 node::Start(uv_loop_s*, int, char const* const*, int, char const* const*) + 366
37  node                          	0x0000000100762603 node::Start(int, char**) + 474
38  node                          	0x0000000100002534 start + 52

Thread 1:
0   libsystem_kernel.dylib        	0x00007fff78e39e7e __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff78f75662 _pthread_cond_wait + 732
2   node                          	0x0000000100831fef uv_cond_wait + 9
3   node                          	0x00000001007a1991 node::TaskQueue<v8::Task>::BlockingPop() + 55
4   node                          	0x00000001007a13d1 node::BackgroundRunner(void*) + 46
5   libsystem_pthread.dylib       	0x00007fff78f746c1 _pthread_body + 340
6   libsystem_pthread.dylib       	0x00007fff78f7456d _pthread_start + 377
7   libsystem_pthread.dylib       	0x00007fff78f73c5d thread_start + 13

Thread 2:
0   libsystem_kernel.dylib        	0x00007fff78e39e7e __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff78f75662 _pthread_cond_wait + 732
2   node                          	0x0000000100831fef uv_cond_wait + 9
3   node                          	0x00000001007a1991 node::TaskQueue<v8::Task>::BlockingPop() + 55
4   node                          	0x00000001007a13d1 node::BackgroundRunner(void*) + 46
5   libsystem_pthread.dylib       	0x00007fff78f746c1 _pthread_body + 340
6   libsystem_pthread.dylib       	0x00007fff78f7456d _pthread_start + 377
7   libsystem_pthread.dylib       	0x00007fff78f73c5d thread_start + 13

Thread 3:
0   libsystem_kernel.dylib        	0x00007fff78e39e7e __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff78f75662 _pthread_cond_wait + 732
2   node                          	0x0000000100831fef uv_cond_wait + 9
3   node                          	0x00000001007a1991 node::TaskQueue<v8::Task>::BlockingPop() + 55
4   node                          	0x00000001007a13d1 node::BackgroundRunner(void*) + 46
5   libsystem_pthread.dylib       	0x00007fff78f746c1 _pthread_body + 340
6   libsystem_pthread.dylib       	0x00007fff78f7456d _pthread_start + 377
7   libsystem_pthread.dylib       	0x00007fff78f73c5d thread_start + 13

Thread 4:
0   libsystem_kernel.dylib        	0x00007fff78e39e7e __psynch_cvwait + 10
1   libsystem_pthread.dylib       	0x00007fff78f75662 _pthread_cond_wait + 732
2   node                          	0x0000000100831fef uv_cond_wait + 9
3   node                          	0x00000001007a1991 node::TaskQueue<v8::Task>::BlockingPop() + 55
4   node                          	0x00000001007a13d1 node::BackgroundRunner(void*) + 46
5   libsystem_pthread.dylib       	0x00007fff78f746c1 _pthread_body + 340
6   libsystem_pthread.dylib       	0x00007fff78f7456d _pthread_start + 377
7   libsystem_pthread.dylib       	0x00007fff78f73c5d thread_start + 13

Thread 5:
0   libsystem_kernel.dylib        	0x00007fff78e30eb2 semaphore_wait_trap + 10
1   node                          	0x0000000100831ec4 uv_sem_wait + 16
2   node                          	0x00000001007d50b4 node::inspector::(anonymous namespace)::StartIoThreadMain(void*) + 21
3   libsystem_pthread.dylib       	0x00007fff78f746c1 _pthread_body + 340
4   libsystem_pthread.dylib       	0x00007fff78f7456d _pthread_start + 377
5   libsystem_pthread.dylib       	0x00007fff78f73c5d thread_start + 13

Thread 6:
0   libsystem_kernel.dylib        	0x00007fff78e3a1d2 __semwait_signal + 10
1   libsystem_c.dylib             	0x00007fff78db5774 nanosleep + 199
2   libc++.1.dylib                	0x00007fff76d6a934 std::__1::this_thread::sleep_for(std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > const&) + 73
3   isolated_vm.node              	0x0000000103eb5f53 ivm::PlatformDelegate::CallDelayedOnForegroundThread(v8::Isolate*, v8::Task*, double)::'lambda'()::operator()() const + 99
4   isolated_vm.node              	0x0000000103eb5e7d void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, ivm::PlatformDelegate::CallDelayedOnForegroundThread(v8::Isolate*, v8::Task*, double)::'lambda'()> >(void*) + 45
5   libsystem_pthread.dylib       	0x00007fff78f746c1 _pthread_body + 340
6   libsystem_pthread.dylib       	0x00007fff78f7456d _pthread_start + 377
7   libsystem_pthread.dylib       	0x00007fff78f73c5d thread_start + 13

Thread 0 crashed with X86 Thread State (64-bit):
  rax: 0x0000000000000000  rbx: 0x0000000104804200  rcx: 0x0000000000000001  rdx: 0x0000000000000000
  rdi: 0x0000000000200000  rsi: 0x0000000000400000  rbp: 0x00007ffeefbfd640  rsp: 0x00007ffeefbfd250
   r8: 0x0000000000000000   r9: 0x0000000000000000  r10: 0x00000000103806d5  r11: 0x0000000000000001
  r12: 0x0000000000000001  r13: 0x0000000000000001  r14: 0x0000000104876208  r15: 0x0000000103a07af0
  rip: 0x00000001001a928d  rfl: 0x0000000000010202  cr2: 0x000000010066f313
  
Logical CPU:     0
Error Code:      0x0200014e
Trap Number:     133


Binary Images:
       0x100000000 -        0x100e31bdf +node (???) <3710F1B7-0B39-3D3C-A6BB-926C35289B97> /usr/local/bin/node
       0x101a73000 -        0x101bd0fff +libicui18n.59.dylib (0) <254E3D9F-1737-34F2-9139-2EC3C20D57AE> /usr/local/opt/icu4c/lib/libicui18n.59.dylib
       0x101caf000 -        0x101db1ff3 +libicuuc.59.dylib (0) <E77E3BDF-AA71-3B39-A645-4772F7BA24E9> /usr/local/opt/icu4c/lib/libicuuc.59.dylib
       0x101e1e000 -        0x103731fff +libicudata.59.1.dylib (0) <9423069A-AEDD-339F-90CD-23A846D72CB9> /usr/local/opt/icu4c/lib/libicudata.59.1.dylib
       0x103e87000 -        0x103ed8ff7 +isolated_vm.node (???) <47410F47-8CCA-3588-A8C4-CA88B3B0D81E> /tmp/*/isolated_vm.node
       0x10503c000 -        0x10508698f  dyld (519.2.1) <002B0442-3D59-3159-BA10-1C0A77859C6A> /usr/lib/dyld
    0x7fff516fe000 -     0x7fff51b9dfff  com.apple.CoreFoundation (6.9 - 1443.13) <2881430B-73E5-32C1-B62D-7CEB68A616F5> /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation
    0x7fff765e6000 -     0x7fff76619fff  libclosured.dylib (519.2.1) <31A6AC03-8F51-367E-9E00-FF0F1AD10F6F> /usr/lib/closure/libclosured.dylib
    0x7fff7678f000 -     0x7fff76790ff3  libDiagnosticMessagesClient.dylib (104) <9712E980-76EE-3A89-AEA6-DF4BAF5C0574> /usr/lib/libDiagnosticMessagesClient.dylib
    0x7fff76af7000 -     0x7fff76af8ff3  libSystem.B.dylib (1252) <BBBE6ABC-FD84-30A3-B699-95F1D6EFB334> /usr/lib/libSystem.B.dylib
    0x7fff76d23000 -     0x7fff76d79fff  libc++.1.dylib (400.9) <FCF5E1F6-2B04-3545-8004-F3AB32FED172> /usr/lib/libc++.1.dylib
    0x7fff76d7a000 -     0x7fff76d9eff7  libc++abi.dylib (400.7) <217656D5-BC40-37FF-B322-91CB2AAD4F34> /usr/lib/libc++abi.dylib
    0x7fff77845000 -     0x7fff77a6bffb  libicucore.A.dylib (59117.0.1) <EC29683E-E9DE-3100-8F75-D1FEBB82AAB2> /usr/lib/libicucore.A.dylib
    0x7fff780e7000 -     0x7fff784d57e7  libobjc.A.dylib (723) <93A92316-DE1E-378C-8891-99720B50D075> /usr/lib/libobjc.A.dylib
    0x7fff78ad4000 -     0x7fff78ae6ffb  libz.1.dylib (70) <48C67CFC-940D-3857-8DAD-857774605352> /usr/lib/libz.1.dylib
    0x7fff78b83000 -     0x7fff78b87ff7  libcache.dylib (80) <354F3B7D-404E-3398-9EBF-65CA2CE65211> /usr/lib/system/libcache.dylib
    0x7fff78b88000 -     0x7fff78b92ff3  libcommonCrypto.dylib (60118.1.1) <6C502A55-3B54-3B48-BA7B-FA39F56C0B1E> /usr/lib/system/libcommonCrypto.dylib
    0x7fff78b93000 -     0x7fff78b9afff  libcompiler_rt.dylib (62) <4487CFBA-A5D7-3282-9E6B-94CAD7BE507E> /usr/lib/system/libcompiler_rt.dylib
    0x7fff78b9b000 -     0x7fff78ba3fff  libcopyfile.dylib (146) <7E4BD264-5617-339B-AC73-E8D07EF2C51D> /usr/lib/system/libcopyfile.dylib
    0x7fff78ba4000 -     0x7fff78c28ff7  libcorecrypto.dylib (562) <7974762C-DEF7-3056-9856-9821C27846DB> /usr/lib/system/libcorecrypto.dylib
    0x7fff78caf000 -     0x7fff78ce8ff7  libdispatch.dylib (913.1.6) <0DD78497-6A2A-350A-99EF-15BF41EA07DD> /usr/lib/system/libdispatch.dylib
    0x7fff78ce9000 -     0x7fff78d06ff7  libdyld.dylib (519.2.1) <2597D818-42D2-3375-BD9D-451D5942A6BA> /usr/lib/system/libdyld.dylib
    0x7fff78d07000 -     0x7fff78d07ffb  libkeymgr.dylib (28) <6D84A96F-C65B-38EC-BDB5-21FD2C97E7B2> /usr/lib/system/libkeymgr.dylib
    0x7fff78d15000 -     0x7fff78d15ff7  liblaunch.dylib (1205.1.10) <5AD77A68-BB4D-33AA-AA4F-DF51D0972FD9> /usr/lib/system/liblaunch.dylib
    0x7fff78d16000 -     0x7fff78d1affb  libmacho.dylib (900.0.1) <756F2553-07B6-3B42-ACEA-2F0F1A5E8D0F> /usr/lib/system/libmacho.dylib
    0x7fff78d1b000 -     0x7fff78d1dff3  libquarantine.dylib (86) <6AC8773F-3817-3D82-99C2-01BABB9C3CBB> /usr/lib/system/libquarantine.dylib
    0x7fff78d1e000 -     0x7fff78d1fff3  libremovefile.dylib (45) <912FA211-DD8C-3C92-8424-21B89F8B10FD> /usr/lib/system/libremovefile.dylib
    0x7fff78d20000 -     0x7fff78d37fff  libsystem_asl.dylib (356.1.1) <94972913-9DF0-3C78-847C-43E58919E3DA> /usr/lib/system/libsystem_asl.dylib
    0x7fff78d38000 -     0x7fff78d38fff  libsystem_blocks.dylib (67) <F2493BB5-B1C6-3C4D-9F1F-1B402E0F1DB7> /usr/lib/system/libsystem_blocks.dylib
    0x7fff78d39000 -     0x7fff78dc2fff  libsystem_c.dylib (1244.1.7) <2D4C21C0-9938-3552-8DC1-2C1CFAA10D38> /usr/lib/system/libsystem_c.dylib
    0x7fff78dc3000 -     0x7fff78dc6ffb  libsystem_configuration.dylib (963) <D7EFEAE6-22A0-348E-BBBE-44FFD41934FA> /usr/lib/system/libsystem_configuration.dylib
    0x7fff78dc7000 -     0x7fff78dcaffb  libsystem_coreservices.dylib (51) <21A488D0-2D07-344E-8631-CC8B2A246F35> /usr/lib/system/libsystem_coreservices.dylib
    0x7fff78dcb000 -     0x7fff78dccfff  libsystem_darwin.dylib (1244.1.7) <552C05CA-D151-3F93-B570-413340BDA9C7> /usr/lib/system/libsystem_darwin.dylib
    0x7fff78dcd000 -     0x7fff78dd3ff7  libsystem_dnssd.dylib (878.1.1) <6E28973E-A258-36F6-ACFB-259ED5885C7A> /usr/lib/system/libsystem_dnssd.dylib
    0x7fff78dd4000 -     0x7fff78e1dff7  libsystem_info.dylib (517) <483BE95B-62EB-3663-ACB3-9915A40C70F5> /usr/lib/system/libsystem_info.dylib
    0x7fff78e1e000 -     0x7fff78e43ff7  libsystem_kernel.dylib (4570.1.46) <71BA15CB-3056-3CBD-A5F5-EE61566EEA0C> /usr/lib/system/libsystem_kernel.dylib
    0x7fff78e44000 -     0x7fff78e8ffcb  libsystem_m.dylib (3146) <ABB1B85F-9FFE-31B8-AD4F-E39A30794A93> /usr/lib/system/libsystem_m.dylib
    0x7fff78e90000 -     0x7fff78eaffff  libsystem_malloc.dylib (140.1.1) <9F0745FF-B92F-330D-8812-BB74001D1D33> /usr/lib/system/libsystem_malloc.dylib
    0x7fff78eb0000 -     0x7fff78f53ff3  libsystem_network.dylib (1229.1.5) <A51EB0A4-9AA5-3F84-8E25-DD8EABE0F97E> /usr/lib/system/libsystem_network.dylib
    0x7fff78f54000 -     0x7fff78f5effb  libsystem_networkextension.dylib (767.1.4) <E842569D-00BA-3DE7-AD5A-9EF33422CF3E> /usr/lib/system/libsystem_networkextension.dylib
    0x7fff78f5f000 -     0x7fff78f68ff3  libsystem_notify.dylib (172) <98EA3D62-7C86-30DE-8261-D020D2F1EFF3> /usr/lib/system/libsystem_notify.dylib
    0x7fff78f69000 -     0x7fff78f70ff7  libsystem_platform.dylib (161) <9F5A67F7-BC65-300F-BD74-07E7732D6372> /usr/lib/system/libsystem_platform.dylib
    0x7fff78f71000 -     0x7fff78f7cff7  libsystem_pthread.dylib (301.1.6) <6D0B0110-2B44-3D3C-B672-BD08FE46378A> /usr/lib/system/libsystem_pthread.dylib
    0x7fff78f7d000 -     0x7fff78f80ffb  libsystem_sandbox.dylib (765.1.8) <EC909728-0365-3710-B00B-0BCFCE03DC71> /usr/lib/system/libsystem_sandbox.dylib
    0x7fff78f81000 -     0x7fff78f82ff3  libsystem_secinit.dylib (30) <F06ADB8F-9E94-34A7-B3C9-2C22FDD14BAD> /usr/lib/system/libsystem_secinit.dylib
    0x7fff78f83000 -     0x7fff78f8aff7  libsystem_symptoms.dylib (820.1.4) <BF0566B2-9475-3B5C-8641-7910F313BA3C> /usr/lib/system/libsystem_symptoms.dylib
    0x7fff78f8b000 -     0x7fff78f9eff7  libsystem_trace.dylib (829.1.2) <10955EBB-1AC8-3085-9A2D-F3088CA2DF71> /usr/lib/system/libsystem_trace.dylib
    0x7fff78fa0000 -     0x7fff78fa5ff7  libunwind.dylib (35.3) <6D4FCD49-D2A9-3233-95C7-A7635CE265F2> /usr/lib/system/libunwind.dylib
    0x7fff78fa6000 -     0x7fff78fd1ff7  libxpc.dylib (1205.1.10) <E7C5DB12-6D0E-3D1E-A743-F750DF112F5F> /usr/lib/system/libxpc.dylib

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 697418
    thread_create: 0
    thread_set_state: 0

VM Region Summary:
ReadOnly portion of Libraries: Total=257.8M resident=0K(0%) swapped_out_or_unallocated=257.8M(100%)
Writable regions: Total=115.4M written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=115.4M(100%)
 
                                VIRTUAL   REGION 
REGION TYPE                        SIZE    COUNT (non-coalesced) 
===========                     =======  ======= 
Kernel Alloc Once                    8K        2 
MALLOC                            63.2M       11 
MALLOC guard page                   16K        5 
Memory Tag 255                     1.0G       76 
Memory Tag 255 (reserved)           24K        7         reserved VM address space (unallocated)
STACK GUARD                       56.0M        8 
Stack                             40.6M        8 
__DATA                            4564K       52 
__LINKEDIT                       200.3M        8 
__TEXT                            57.5M       50 
__UNICODE                          556K        2 
shared memory                        8K        3 
===========                     =======  ======= 
TOTAL                              1.4G      220 
TOTAL, minus reserved VM space     1.4G      220 

Model: MacBookPro13,3, BootROM MBP133.0233.B00, 4 processors, Intel Core i7, 2.7 GHz, 16 GB, SMC 2.38f7
Graphics: Intel HD Graphics 530, Intel HD Graphics 530, Built-In
Graphics: Radeon Pro 460, AMD Radeon Pro 460, PCIe, 4 GB
Memory Module: BANK 0/DIMM0, 8 GB, LPDDR3, 2133 MHz, 0x802C, 0x4D5435324C31473332443450472D30393320
Memory Module: BANK 1/DIMM0, 8 GB, LPDDR3, 2133 MHz, 0x802C, 0x4D5435324C31473332443450472D30393320
AirPort: spairport_wireless_card_type_airport_extreme (0x14E4, 0x15A), Broadcom BCM43xx 1.0 (7.77.37.0.1a1)
Bluetooth: Version 6.0.0f7, 3 services, 27 devices, 1 incoming serial ports
Network Service: Wi-Fi, AirPort, en0
USB Device: USB 3.0 Bus
USB Device: iBridge
Thunderbolt Bus: MacBook Pro, Apple Inc., 22.2
Thunderbolt Bus: MacBook Pro, Apple Inc., 22.2

Inspector question with multiple contexts

The inspector has been working great, but I'm running into issues where breakpoints don't work anymore (either manually set in the inspector or via the debugger keyword) when I'm using a new context.

Our development server will reload the code and create a new context for each request. The context and isolate still both have the {inspector: true} option on them.

The script has a different filename too (I'm appending the sha1 of the source to the filename.)

Any idea why the inspector would stop working in these cases?

Passing a Reference through an ExternalCopy breaks the reference

Given an object like:

{ functionA: Reference { typeof: 'function' }, numberB: 1 }

Passing set object through ExternalCopy's .copyInto()/.copy() results in the following:

{ functionA: { typeof: 'function' }, numberB: 1 }

Not sure if this is the intended behaviour, but it looks like it tries to serialise the Reference as an object. I'm trying to pass an object containing some functions from the main isolate to another isolate.

Is there a way in which it could keep the original, or .copy() it?

Sample code:

const ivm = require('isolated-vm');

const ref = new ivm.Reference(function aFunction() {});

const objectWithRef = { fn: ref, nr: 1 };

console.dir(ref);
console.dir(new ivm.ExternalCopy(ref).copy());
console.dir(objectWithRef);
console.dir(new ivm.ExternalCopy(objectWithRef).copy());
console.dir(new ivm.Reference(objectWithRef).deref()); // will not work in other isolates

output:

Reference { typeof: 'function' }
{ typeof: 'function' }
{ fn: Reference { typeof: 'function' }, nr: 1 }
{ fn: { typeof: 'function' }, nr: 1 }
{ fn: Reference { typeof: 'function' }, nr: 1 }

Access node's I/O from any Isolate

Hi!
I was wandering if there is any possibility to access the file system or make network calls from an Isolate without a stub in the main isolate.

My goal here is to possibly make a require-like system that can be used inside any Isolate and load code via it. I tried to share the require function of the main isolate, but the only way i could do it was through a stub that requires the module and then passes it as a reference, but in my understanding, that will still execute on the main isolate.

Any guidance will be appreciated ๐Ÿ˜ƒ

Mutex lock failed: Invalid argument

I'm getting a misleading error with this basic setup:

const ivm = require('isolated-vm');
const isolate = new ivm.Isolate();
const context = isolate.createContextSync();
const script = isolate.compileScriptSync('');
script.runSync(context);

Error:

libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument

Build requirements for 1.1.0+?

I started getting build errors for our docker container, based on the official node.js image

Builds were fine for 1.0.2, but not 1.1.0.

Oddly, travis can build this fine, but not within our docker image. It's based off of node:8, which is based off of debian jessie: https://github.com/nodejs/docker-node/blob/4c7763dc2cb067becf12ea4bd55e88b881ccba2b/8/Dockerfile

Logs:

make: Entering directory '/usr/src/app/node_modules/isolated-vm/build'
  CXX(target) Release/obj.target/isolated_vm/src/isolate/allocator.o
In file included from ../src/isolate/allocator.cc:2:0:
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::data' [-Wmissing-field-initializers]
   v8::StartupData startup_data {};
                                 ^
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::raw_size' [-Wmissing-field-initializers]
  CXX(target) Release/obj.target/isolated_vm/src/isolate/class_handle.o
In file included from ../src/isolate/remote_handle.h:3:0,
                 from ../src/isolate/util.h:6,
                 from ../src/isolate/convert_param.h:3,
                 from ../src/isolate/class_handle.h:4,
                 from ../src/isolate/class_handle.cc:1:
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::data' [-Wmissing-field-initializers]
   v8::StartupData startup_data {};
                                 ^
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::raw_size' [-Wmissing-field-initializers]
  CXX(target) Release/obj.target/isolated_vm/src/isolate/environment.o
In file included from ../src/isolate/environment.cc:1:0:
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::data' [-Wmissing-field-initializers]
   v8::StartupData startup_data {};
                                 ^
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::raw_size' [-Wmissing-field-initializers]
  CXX(target) Release/obj.target/isolated_vm/src/isolate/holder.o
In file included from ../src/isolate/holder.cc:2:0:
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::data' [-Wmissing-field-initializers]
   v8::StartupData startup_data {};
                                 ^
../src/isolate/environment.h:205:33: warning: missing initializer for member 'v8::StartupData::raw_size' [-Wmissing-field-initializers]
../src/isolate/holder.cc: In member function 'void ivm::IsolateHolder::Dispose()':
../src/isolate/holder.cc:14:102: error: no matching function for call to 'atomic_exchange(std::shared_ptr<ivm::IsolateEnvironment>*, std::shared_ptr<ivm::IsolateEnvironment>)'
  shared_ptr<IsolateEnvironment> tmp = std::atomic_exchange(&isolate, shared_ptr<IsolateEnvironment>());
                                                                                                      ^
../src/isolate/holder.cc:14:102: note: candidates are:
In file included from ../src/isolate/environment.h:8:0,
                 from ../src/isolate/holder.cc:2:
/usr/include/c++/4.9/atomic:914:5: note: template<class _ITp> _ITp std::atomic_exchange(std::atomic<_ITp>*, _ITp)
     atomic_exchange(atomic<_ITp>* __a, _ITp __i) noexcept
     ^
/usr/include/c++/4.9/atomic:914:5: note:   template argument deduction/substitution failed:
../src/isolate/holder.cc:14:102: note:   'std::shared_ptr<ivm::IsolateEnvironment>' is not derived from 'std::atomic<_ITp>'
  shared_ptr<IsolateEnvironment> tmp = std::atomic_exchange(&isolate, shared_ptr<IsolateEnvironment>());
                                                                                                      ^
In file included from ../src/isolate/environment.h:8:0,
                 from ../src/isolate/holder.cc:2:
/usr/include/c++/4.9/atomic:919:5: note: template<class _ITp> _ITp std::atomic_exchange(volatile std::atomic<_ITp>*, _ITp)
     atomic_exchange(volatile atomic<_ITp>* __a, _ITp __i) noexcept
     ^
/usr/include/c++/4.9/atomic:919:5: note:   template argument deduction/substitution failed:
../src/isolate/holder.cc:14:102: note:   'std::shared_ptr<ivm::IsolateEnvironment>' is not derived from 'volatile std::atomic<_ITp>'
  shared_ptr<IsolateEnvironment> tmp = std::atomic_exchange(&isolate, shared_ptr<IsolateEnvironment>());
                                                                                                      ^
../src/isolate/holder.cc: In member function 'std::shared_ptr<ivm::IsolateEnvironment> ivm::IsolateHolder::GetIsolate()':
../src/isolate/holder.cc:24:34: error: no matching function for call to 'atomic_load(std::shared_ptr<ivm::IsolateEnvironment>*)'
  return std::atomic_load(&isolate);
                                  ^
../src/isolate/holder.cc:24:34: note: candidates are:
In file included from ../src/isolate/environment.h:8:0,
                 from ../src/isolate/holder.cc:2:
/usr/include/c++/4.9/atomic:904:5: note: template<class _ITp> _ITp std::atomic_load(const std::atomic<_ITp>*)
     atomic_load(const atomic<_ITp>* __a) noexcept
     ^
/usr/include/c++/4.9/atomic:904:5: note:   template argument deduction/substitution failed:
../src/isolate/holder.cc:24:34: note:   'std::shared_ptr<ivm::IsolateEnvironment>' is not derived from 'const std::atomic<_ITp>'
  return std::atomic_load(&isolate);
                                  ^
In file included from ../src/isolate/environment.h:8:0,
                 from ../src/isolate/holder.cc:2:
/usr/include/c++/4.9/atomic:909:5: note: template<class _ITp> _ITp std::atomic_load(const volatile std::atomic<_ITp>*)
     atomic_load(const volatile atomic<_ITp>* __a) noexcept
     ^
/usr/include/c++/4.9/atomic:909:5: note:   template argument deduction/substitution failed:
../src/isolate/holder.cc:24:34: note:   'std::shared_ptr<ivm::IsolateEnvironment>' is not derived from 'const volatile std::atomic<_ITp>'
  return std::atomic_load(&isolate);
                                  ^
../src/isolate/holder.cc: In member function 'void ivm::IsolateHolder::ScheduleTask(std::unique_ptr<ivm::Runnable>, bool, bool)':
../src/isolate/holder.cc:28:64: error: no matching function for call to 'atomic_load(std::shared_ptr<ivm::IsolateEnvironment>*)'
  shared_ptr<IsolateEnvironment> ref = std::atomic_load(&isolate);
                                                                ^
../src/isolate/holder.cc:28:64: note: candidates are:
In file included from ../src/isolate/environment.h:8:0,
                 from ../src/isolate/holder.cc:2:
/usr/include/c++/4.9/atomic:904:5: note: template<class _ITp> _ITp std::atomic_load(const std::atomic<_ITp>*)
     atomic_load(const atomic<_ITp>* __a) noexcept
     ^
/usr/include/c++/4.9/atomic:904:5: note:   template argument deduction/substitution failed:
../src/isolate/holder.cc:28:64: note:   'std::shared_ptr<ivm::IsolateEnvironment>' is not derived from 'const std::atomic<_ITp>'
  shared_ptr<IsolateEnvironment> ref = std::atomic_load(&isolate);
                                                                ^
In file included from ../src/isolate/environment.h:8:0,
                 from ../src/isolate/holder.cc:2:
/usr/include/c++/4.9/atomic:909:5: note: template<class _ITp> _ITp std::atomic_load(const volatile std::atomic<_ITp>*)
     atomic_load(const volatile atomic<_ITp>* __a) noexcept
     ^
/usr/include/c++/4.9/atomic:909:5: note:   template argument deduction/substitution failed:
../src/isolate/holder.cc:28:64: note:   'std::shared_ptr<ivm::IsolateEnvironment>' is not derived from 'const volatile std::atomic<_ITp>'
  shared_ptr<IsolateEnvironment> ref = std::atomic_load(&isolate);
                                                                ^
../src/isolate/holder.cc: In member function 'std::shared_ptr<ivm::IsolateEnvironment> ivm::IsolateHolder::GetIsolate()':
../src/isolate/holder.cc:25:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
isolated_vm.target.mk:115: recipe for target 'Release/obj.target/isolated_vm/src/isolate/holder.o' failed
make: Leaving directory '/usr/src/app/node_modules/isolated-vm/build'
make: *** [Release/obj.target/isolated_vm/src/isolate/holder.o] Error 1
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/local/lib/node_modules/npm/node_modules/node-gyp/lib/build.js:258:23)
gyp ERR! stack     at emitTwo (events.js:126:13)
gyp ERR! stack     at ChildProcess.emit (events.js:214:7)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:198:12)
gyp ERR! System Linux 4.4.0-101-generic
gyp ERR! command "/usr/local/bin/node" "/usr/local/lib/node_modules/npm/node_modules/node-gyp/bin/node-gyp.js" "rebuild" "--release"
gyp ERR! cwd /usr/src/app/node_modules/isolated-vm
gyp ERR! node -v v8.9.4
gyp ERR! node-gyp -v v3.6.2
gyp ERR! not ok 

Invoke in VM function with argument AND timeout support

There is two ways to execute a piece of code from the VM:

  • Compile and run a script on the context.
  • Get a reference from a function living in the context, and call apply on it.

With the first solution, we can supply a timeout parameter to the run method in order to limit the execution time. But with this method it is not possible to pass parameters "on the stack". We have to store values in the global context then access them from the script we execute.

With the second method, we can pass (transferable) arguments to the method, like callback etc. But there is no way to pass a timeout to the apply method.

CPU/wall time per context?

Would it be possible to get those timings per context? I assume it's a matter of summing the time during which the context "has the lock" on the isolate? (that would probably be wall time though)

applySyncPromise segfault

Hey there,

We're loving the new applySyncPromise function and plan on using it to make our isolates leaner and more robust.

In my tests, under high concurrency conditions, it seems like I inevitably end up with a segfault like:

PID 16308 received SIGSEGV for address: 0x0
0   segfault-handler.node               0x0000000107178168 _ZL16segfault_handleriP9__siginfoPv + 280
1   libsystem_platform.dylib            0x00007fffe68deb3a _sigtramp + 26
2   node                                0x000000010043326b _ZNK2v88internal23StackTraceFrameIterator12IsValidFrameEPNS0_10StackFrameE + 127
3   isolated_vm.node                    0x0000000103f1b3f8 _ZN3ivm14ThreePhaseTask7RunSyncERNS_13IsolateHolderEb + 296
4   isolated_vm.node                    0x0000000103f4be5f _ZN3ivm14ThreePhaseTask3RunILi4ENS_11ApplyRunnerEJRNS_15ReferenceHandleERN2v810MaybeLocalINS5_5ValueEEERNS6_INS5_5ArrayEEERNS6_INS5_6ObjectEEERNSt3__110shared_ptrINS_12RemoteHandleINS5_7ContextEEEEERNSH_INSI_IS7_EEEEEEENS5_5LocalIS7_EERNS_13IsolateHolderEDpOT1_ + 175
5   isolated_vm.node                    0x0000000103f4bf57 _ZN3ivm14FunctorRunners11RunCallbackIZNS_11ClassHandle17ParameterizeEntryILin1EPFN2v85LocalINS4_5ValueEEEPNS_15ReferenceHandleENS4_10MaybeLocalIS6_EENSA_INS4_5ArrayEEENSA_INS4_6ObjectEEEEXadL_ZNS2_10MethodCastIMS8_FS7_SB_SD_SF_EE6InvokeIXadL_ZNS8_5ApplyILi4EEES7_SB_SD_SF_EEEES7_S9_SB_SD_SF_EEEEvRKNS4_20FunctionCallbackInfoIS6_EEEUlvE_SQ_EEvRT0_T_ + 135
6   node                                0x00000001001cf62a _ZN2v88internal25FunctionCallbackArguments4CallEPFvRKNS_20FunctionCallbackInfoINS_5ValueEEEE + 430
7   node                                0x0000000100216030 _ZN2v88internal12_GLOBAL__N_119HandleApiCallHelperILb0EEENS0_11MaybeHandleINS0_6ObjectEEEPNS0_7IsolateENS0_6HandleINS0_10HeapObjectEEESA_NS8_INS0_20FunctionTemplateInfoEEENS8_IS4_EENS0_16BuiltinArgumentsE + 775
8   node                                0x000000010021574a _ZN2v88internalL26Builtin_Impl_HandleApiCallENS0_16BuiltinArgumentsEPNS0_7IsolateE + 259
9   ???                                 0x000002d21b7842fd 0x0 + 3101427254013
libc++abi.dylib: terminating

Not entirely sure what triggers that.

Sometimes I also get the following with no stacktrace:

libc++abi.dylib: terminating with uncaught exception of type std::__1::system_error: mutex lock failed: Invalid argument

Running node 8.10 on macos.

I'm not sure if this happens because something is being released too early? I can't reproduce in a simpler test case releasing right after running my function in an infinite loop.

GlobalObject leaky?

Probably our fault, but I was wondering if the global object might leak memory even after the context has been released.

We've been having ever-growing heap on isolates. I've used the inspector to record an allocation timeline and noticed the global object seems to appear very often.

image

image

image

I've been careful not to keep references of anything from the context and releasing it after each use.

That's in development which goes like this:

  • An isolate is created with 128 mb memory limit
  • A context is created on each http request, it's bootstrapped and then we run the user's script
  • We dispatch the fetch event in the context
  • After all is done with the request (FetchEvent has responded) we "finalize" the context (wait on all timers and all "callbacks" that are supposed to call back into the isolate) and then we release the context.

All references to the timers and callbacks are removed.

Any pointers on how to keep the isolate lean after each request? I suspect some of our bootstrapped code is not memory efficient, but this seems kind of intense.

That allocation timeline was made on a very small app, all it does it respond to a callback with a default Response with some text. That heap grew that much after only about 30 requests. Basically each time we keep the isolate around and create a new context, it adds 1.6MB onto the heap of the isolate and it's not obvious how to get rid of it.

index.js references debug build

The index.js file references the debug build:

module.exports = require('./build/Debug/isolated_vm').ivm;

When installed thru npm, the build is stored in the Release directory and thus does not work.

Wire up existing `console` in v8?

v8 has console stuff built in but there's no stdout/err up to it (I think that's all that's missing). Is there a way to hook it up through isolated-vm?

Segfault in SessionHandle and another unknown symbol

I think I reported this in a comment, but I figured I'd make it official with an issue of its own:

This seems to happen when disposing of an isolate (sometimes) when putting way too much load on it.

PID 18013 received SIGSEGV for address: 0x118
0   segfault-handler.node               0x0000000103fed168 _ZL16segfault_handleriP9__siginfoPv + 280
1   libsystem_platform.dylib            0x00007fffc3515b3a _sigtramp + 26
2   isolated_vm.node                    0x0000000106b2ca48 _ZGVZN3ivm13SessionHandle16TemplateSpecificEvE4tmpl + 42544
3   node                                0x000000010046e302 _ZN2v88internal4Heap19ExternalStringTable8TearDownEv + 260
4   node                                0x000000010046e05d _ZN2v88internal4Heap8TearDownEv + 543
5   node                                0x00000001004f0979 _ZN2v88internal7Isolate6DeinitEv + 557
6   node                                0x00000001004f0697 _ZN2v88internal7Isolate8TearDownEv + 77
7   isolated_vm.node                    0x0000000106ace8fe _ZN3ivm18IsolateEnvironmentD2Ev + 958
8   libc++.1.dylib                      0x00007fffc1ed1dae _ZNSt3__119__shared_weak_count16__release_sharedEv + 44
9   isolated_vm.node                    0x0000000106acbc12 _ZN3ivm18IsolateEnvironment9Scheduler17AsyncCallbackPoolEbPv + 82
10  isolated_vm.node                    0x0000000106ad0608 _ZZN13thread_pool_t10new_threadEvENKUlvE_clEv + 136
11  isolated_vm.node                    0x0000000106ad050d _ZNSt3__114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEZN13thread_pool_t10new_threadEvEUlvE_EEEEEPvSA_ + 45
12  libsystem_pthread.dylib             0x00007fffc351f93b _pthread_body + 180
13  libsystem_pthread.dylib             0x00007fffc351f887 _pthread_body + 0
14  libsystem_pthread.dylib             0x00007fffc351f08d thread_start + 13

I've also gotten this one, also related to disposition.

PID 18114 received SIGSEGV for address: 0x118
0   segfault-handler.node               0x00000001038f5168 _ZL16segfault_handleriP9__siginfoPv + 280
1   libsystem_platform.dylib            0x00007fffc3515b3a _sigtramp + 26
2   ???                                 0x0000000000000000 0x0 + 0
3   node                                0x000000010046e26e _ZN2v88internal4Heap19ExternalStringTable8TearDownEv + 112
4   node                                0x000000010046e05d _ZN2v88internal4Heap8TearDownEv + 543
5   node                                0x00000001004f0979 _ZN2v88internal7Isolate6DeinitEv + 557
6   node                                0x00000001004f0697 _ZN2v88internal7Isolate8TearDownEv + 77
7   isolated_vm.node                    0x00000001062048fe _ZN3ivm18IsolateEnvironmentD2Ev + 958
8   libc++.1.dylib                      0x00007fffc1ed1dae _ZNSt3__119__shared_weak_count16__release_sharedEv + 44
9   isolated_vm.node                    0x0000000106201c12 _ZN3ivm18IsolateEnvironment9Scheduler17AsyncCallbackPoolEbPv + 82
10  isolated_vm.node                    0x0000000106206608 _ZZN13thread_pool_t10new_threadEvENKUlvE_clEv + 136
11  isolated_vm.node                    0x000000010620650d _ZNSt3__114__thread_proxyINS_5tupleIJNS_10unique_ptrINS_15__thread_structENS_14default_deleteIS3_EEEEZN13thread_pool_t10new_threadEvEUlvE_EEEEEPvSA_ + 45
12  libsystem_pthread.dylib             0x00007fffc351f93b _pthread_body + 180
13  libsystem_pthread.dylib             0x00007fffc351f887 _pthread_body + 0
14  libsystem_pthread.dylib             0x00007fffc351f08d thread_start + 13
libc++abi.dylib: terminating

I do my best checking is isolate is disposed at every step of the way, but sometimes the isolate will be disposed between my check and global.set or any other function interacting with the isolate.

Event loop snafu

While integrating isolated-vm within a network service, I noticed some strange behavior with async methods like createContext. When testing alone, everything works, but once integrated, those promises never trigger.

I think there is something fishy with the way those methods interact with event loop. For instance, in the example below, if I add something to the event loop with setTimeout, the createContext will return after the timeout. Without the timeout, the promise resolves immediately:

const ivm = require("isolated-vm");

const i = new ivm.Isolate();
i.createContext().then(() => {
    console.log('got context');
});

setTimeout(() => {
    console.log('timeout');
}, 10000);

Result:

<10 seconds>
timeout
got context

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.