fridgerator / PyNode

Node - Python Interop
154 stars 14 forks source link

Fatal Error: v8::ToLocalChecked Empty MaybeLocal #17

Closed rikvermeer closed 4 years ago

rikvermeer commented 5 years ago

I made a venv which works (python 3.7). The module compiles (node 12), yet I'm getting:

node index.js

FATAL ERROR: v8::ToLocalChecked Empty MaybeLocal.
 1: 0x100078e78 node::Abort() [/usr/local/bin/node]
 2: 0x1000794f6 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
 3: 0x10016a6bc v8::Utils::ReportApiFailure(char const*, char const*) [/usr/local/bin/node]
 4: 0x103d90575 call(Nan::FunctionCallbackInfo<v8::Value> const&) [/Users/rikvermeer/workspace/testpynode/node_modules/@fridgerator/pynode/build/Release/PyNode.node]
 5: 0x103d92439 Nan::imp::FunctionCallbackWrapper(v8::FunctionCallbackInfo<v8::Value> const&) [/Users/rikvermeer/workspace/testpynode/node_modules/@fridgerator/pynode/build/Release/PyNode.node]
 6: 0x1001ccc58 v8::internal::FunctionCallbackArguments::Call(v8::internal::CallHandlerInfo) [/usr/local/bin/node]
 7: 0x1001cc322 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) [/usr/local/bin/node]
 8: 0x1001cbb0a v8::internal::Builtin_Impl_HandleApiCall(v8::internal::BuiltinArguments, v8::internal::Isolate*) [/usr/local/bin/node]
 9: 0x10071a3b9 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [/usr/local/bin/node]
[1]    80065 abort      node index.js

cat index.js

const pynode = require('@fridgerator/pynode');
pynode.startInterpreter();
pynode.appendSysPath('/');
pynode.openFile('test');
let x = pynode.call('add', 1, 2);
//console.log('x: ' + x);

cat test.py

def add(a, b):
  return a + b
fridgerator commented 5 years ago

@rikvermeer Thanks for this issue.

The API has changed recently, and PyNode calls are now async. The last parameter should be a function (error, result) => {}

const pynode = require('@fridgerator/pynode')
pynode.startInterpreter()
pynode.appendSysPath('./')
pynode.openFile('test')
pynode.call('add', 1, 2, (err, result) => {
  if (err) return console.log('error : ', err)
  result === 3 // true
})

However your issue exposed something, that is I need to check that the last parameter passed is a function.

fridgerator commented 5 years ago

Or if you prefer using a promise:

const { promisify } = require('util')
const call = promisify(nodePython.call)
call('add', 1, 2)
  .then(result => console.log(result))
  .catch(error => console.log(error))
drmhessler commented 5 years ago

Thanks for your advice using a promise. Can I use await in the assignment manner suggested by rikvermeer by using var result = await call('add',1,2);

rikvermeer commented 5 years ago

Hi again and thanks for the quick reply!

Im getting a segfault. Can't run valgrind on my current Darwin. I'll try running a debug build of node; maybe i can find some pointers.

cat ./test.py

def add(a, b):
  return a + b

if __name__ == '__main__':
  print(add(1, 2))

python3 ./test.py

3

cat index.js

const pynode = require('@fridgerator/pynode');
pynode.startInterpreter();
pynode.appendSysPath('/');
pynode.openFile('test');

pynode.call('add', 1, 2, (err, result) => {
  //if(err) console.warn(err);
  //console.log(result);
  //result === 3
});

node ./index.js

[1]    28895 segmentation fault  node ./index.js
rikvermeer commented 5 years ago

And with util.promisify

cat index2.js

const pynode = require('@fridgerator/pynode');
const { promisify } = require('util');
const call = promisify(pynode.call);
call('add', 1, 2)
  .then(result => console.log(result))
  .catch(error => console.log(error));

node index2.js

[1]    78858 segmentation fault  node index2.js
rikvermeer commented 5 years ago

The following works though:

pynode.eval("print('hallo')");
fridgerator commented 5 years ago

Right now if python cant find the function to call it just fails (segfault). I'm working on fixing this in another branch among other things (multithreading support).

I would guess that its not finding the add function. If you change pynode.appendSysPath('/'); to pynode.appendSysPath('./'); does this fix the issue?

rikvermeer commented 5 years ago

Ofcourse! It combined nicely with the 'test' module on the venv's syspath :)

Maybe you can add distinction between file loading and module loading?

fridgerator commented 5 years ago

Yes I should, openFile is misleading as its really importing a module / file.