laverdet / isolated-vm Goto Github PK
View Code? Open in Web Editor NEWSecure & isolated JS environments for nodejs
License: ISC License
Secure & isolated JS environments for nodejs
License: ISC License
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.
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.
Would it be possible to get user/system and internal/external CPU usage for code ran into an isolate?
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.
(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?
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 ??
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.
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 **
This code (based on the memory-eating example) usually triggers one of the following two errors:
libc++abi.dylib: terminating with uncaught exception of type ivm::js_error<&(v8::Exception::Error(v8::Local<v8::String>))>: std::exception
Abort trap: 6
or
Segmentation fault: 11
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:
#include <stdlib>
to external_copy.h
.nullptr_t
to std::nullptr_t
in class_handle.h:23:27It might be possible that these be just compiler version issues instead. I tried clang
and gcc-7
.
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.
});
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?
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 :)
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?
This is a very interesting project. Is this used somewhere in production or it is still at the experimention stage?
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:
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.
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)?
It would be interesting to have a method to get the current heap size of an isolate.
Is there a way to get a promise that would resolve when all events scheduled by the context are done?
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.
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.
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.
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
When an error happen at compile time (with createSnapshot or compileScript), the error give no indication of where the error is located.
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.
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.
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);
}
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.
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.
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.
'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
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.
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 primitivesExternalCopy(value).copyInto()
is transferable where value is anythingIs 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.
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.
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
Any plans to support inspecting isolates via the V8 Inspector API? https://github.com/v8/v8/wiki/Debugging-over-the-V8-Inspector-API
I'm not sure if the right packages are imported by default or if we'd need to add the d8 stuff.
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?
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 }
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 ๐
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
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
There is two ways to execute a piece of code from the VM:
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.
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)
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.
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.
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:
fetch
event in the contextrelease
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.
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.
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?
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.
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
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.