Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serial port commnunication does not work inside a Worker Thread #1938

Closed
hugo-a-garcia opened this issue Sep 24, 2019 · 17 comments
Closed

Serial port commnunication does not work inside a Worker Thread #1938

hugo-a-garcia opened this issue Sep 24, 2019 · 17 comments

Comments

@hugo-a-garcia
Copy link

hugo-a-garcia commented Sep 24, 2019

Summary of Problem

Opening a serial port from within a worker thread fails with:

Error: Module did not self-register.

Code to Reproduce the Issue

github repo: hugo-a-garcia/serial-worker

const {
   Worker, isMainThread, parentPort, workerData
} = require('worker_threads');

const SerialPort = require("serialport");
   const Readline = SerialPort.parsers.Readline;

if (isMainThread) {
   console.log("In main thread");

   const worker = new Worker(__filename);
   worker.on('message', msg => {
      console.log(msg);
   });
   worker.on('error', err => {
      console.error("Oops " + err)
   });
   worker.on('exit', (code) => {
      if (code !== 0)
         console.log(`Worker stopped with exit code ${code}`);
   });

} else {
   console.log("In worker thread");
 
   const port = new SerialPort("/dev/ttyACM0", {
       baudRate: 9600
   });
   
   const parser = new Readline
   port.pipe(parser);
   parser.on("data", (data) => console.log(data));
   
   // port.on('readable', function () {
   //     console.log(port.read().toString());
   // });
   
   port.on('error', function (err) {
       console.log('Error: ', err.message);
   });

   parentPort.postMessage("Done.");
}

Versions, Operating System and Hardware

  • SerialPort@? 7.1.5
  • Node.js v? v12.9.1
  • Linux
  • Hardware and chipset? Arduino Uno connected to laptop

Possible related issue: N-API support for node-serialport #1186

@hugo-a-garcia hugo-a-garcia changed the title Serial port commnunication does not work withing a Worker Thread Serial port commnunication does not work inside a Worker Thread Sep 24, 2019
@reconbot
Copy link
Member

I don't know if this would be realted to N-API. I do think you might have found a bug in workers however. =)

@hugo-a-garcia
Copy link
Author

Ok. I submitted a bug report at node:

nodejs/node#29698

@addaleax
Copy link

Not a bug in Node.js. :) Quoting the Worker threads documentation:

Native add-ons can only be loaded from multiple threads if they fulfill certain conditions.

In short, your addon needs to be declared as context-aware and support multiple threads natively. For N-API, it’s assumed that that’s the case.

Just taking a quick look at the source code here, at least the usage of uv_default_loop() is problematic and will mean that the code won’t work on worker threads as-is anyway.

@reconbot
Copy link
Member

Thanks @addaleax, my knowledge around figuring out how to fix this is not great. There’s no reason why we need the default event loop. And there’s no shared context between serial ports so they could in theory work in workers. I imagine the only thing we’d need to do in the cleanup hook is close the port if it’s open. (Open state is normally kept in JS)

Any pointers would be much appreciated. Thanks! 🙏

@addaleax
Copy link

@reconbot You can probably use Node’s GetCurrentEventLoop() and AddEnvironmentCleanupHook()/RemoveEnvironmentCleanupHook() functions to achieve what you need – I don’t think there are NAN wrappers for them, though.

@reconbot
Copy link
Member

Got to start moving to NAPI anyway 🤷‍♂️

@meisterlampe
Copy link

Really tried to understand what has to be done to implement the cleanupHooks, but actually I'm lost in all this c++. This is not my domain :)
I now forward all calls from workers to serial port running in the main thread using the message channel. This is pretty ugly but I'm fine with it at the moment O:-)

@ponikrf
Copy link

ponikrf commented Aug 6, 2020

Hello. Sad news for me.
Everything works if I don't use worker_threads
(test.js)

const SerialPort = require('serialport')
const port = new SerialPort('/dev/tty.usbserial-A7TRF2V', { baudRate: 9600 })
port.on('data', (data) => { console.log(data) })

But if I run the same code through worker_threads I get a very sad message
(main.js)

const {  Worker } = require('worker_threads')
const worker = new Worker('./test.js', {})
worker.on('message', () => { })
bash-3.2$ node ./main.js 
Segmentation fault: 11

In some ways, I found out the essence of the error

FATAL ERROR: v8::HandleScope::CreateHandle() Cannot create a handle without a HandleScope
 1: 0x100c22043 node::Abort() (.cold.1) [/usr/local/bin/node]
 2: 0x10008710d node::FatalError(char const*, char const*) [/usr/local/bin/node]
 3: 0x100087276 node::OnFatalError(char const*, char const*) [/usr/local/bin/node]
 4: 0x10018e2fc v8::Utils::ReportApiFailure(char const*, char const*) [/usr/local/bin/node]
 5: 0x10028bd36 v8::internal::HandleScope::Extend(v8::internal::Isolate*) [/usr/local/bin/node]
 6: 0x100405e0c v8::internal::JSReceiver::GetCreationContext() [/usr/local/bin/node]
 7: 0x1001a0fef v8::Object::CreationContext() [/usr/local/bin/node]
 8: 0x100003e0b node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [/usr/local/bin/node]
 9: 0x10428d125 init(v8::Local<v8::Object>) [/Users/borisbobylev/vrack/devices/rs485/node_modules/@serialport/bindings/build/Release/bindings.node]
10: 0x10428a90b EIO_AfterOpen(uv_work_s*) [/Users/borisbobylev/vrack/devices/rs485/node_modules/@serialport/bindings/build/Release/bindings.node]
11: 0x10070f124 uv__work_done [/usr/local/bin/node]
12: 0x100712753 uv__async_io [/usr/local/bin/node]
13: 0x100722080 uv__io_poll [/usr/local/bin/node]
14: 0x100712b8a uv_run [/usr/local/bin/node]
15: 0x1000bdb79 node::NodeMainInstance::Run() [/usr/local/bin/node]
16: 0x100061cf0 node::Start(int, char**) [/usr/local/bin/node]
17: 0x7fff67a2dcc9 start [/usr/lib/system/libdyld.dylib]
Abort trap: 6

It would be great if there was someone who could fix it. It's bad that there is code that can kill the main process.

OS: MacOS
Node: v14.6.0
Serialport: 9.0.0

Thanks you.

@ValentineStone
Copy link

@ponikrf and anyone hitting this, you can use tiny-worker, it appears to work fine with this and other native addons as a workaround until the worker_threads support is implemented

@reconbot reconbot pinned this issue Jun 23, 2021
@GazHank
Copy link
Contributor

GazHank commented Jun 24, 2021

Based on the discussion, it sounds like migration from NAN to N-API is a stepping stone to resolving this. Is that still understood to be the case?

I believe there was a previous endevour to migrate to N-API #1186

While that attempt was a while ago, I wonder what code or lessons can be gleaned from that previous work?

@GazHank
Copy link
Contributor

GazHank commented Sep 29, 2021

Hi @hugo-a-garcia would you be able to take a look at PR #2305 and give it a try?

While that PR isn't directly trying to address this issue, I think it might be easier to fix this issue in the N-API version. As such if you are able to share info of any errors you find, or perhaps a sample project you are trying to get to work then it might help fix this issue in the next major version of the package :-)

@archfz
Copy link

archfz commented Aug 22, 2022

I am encountering this in a different situation. The callstack seems different as well than what was posted here previously. On the other hand I am not trying to use any worker threads in code that uses node serialport.

My setup is something like this:

  1. rust napi native module that uses serial ports
  2. testing with ava the module
  3. spawning socat for emulating serial port socat PTY,link=/dev/ttyS10,echo=1 PTY,link=/dev/ttyS11,echo=0
  4. the rust addon connects to ttyS10 and writes to it
  5. the test code connects with node serialport to ttyS11
  6. shortly after when I attempt to read in ava from ttyS11 I get this error message
FATAL ERROR: HandleScope::HandleScope Entering the V8 API without proper locking in place
 1: 0xb02930 node::Abort() [node]
 2: 0xa18149 node::FatalError(char const*, char const*) [node]
 3: 0xcdceaa v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: 0xcde40c v8::HandleScope::HandleScope(v8::Isolate*) [node]
 5: 0xab7a86 napi_open_handle_scope [node]
 6: 0x7f24abc1793b Poller::onData(uv_poll_s*, int, int) [/app/node_modules/@serialport/bindings-cpp/prebuilds/linux-x64/node.napi.glibc.node]

Now the rust napi native module that I am attempting to test does use threads, so I think the two somehow conflict, but I hardly grasp how.

@dj-fiorex
Copy link

Hello guys, so it is working now?

@foureight84
Copy link

foureight84 commented Jul 6, 2023

Doesn't look like it. I'm getting the same error:

npx ts-node src/index.ts 
Worker Received: test
Serial baud rate: 115200
Record duration: 60
writing: ATZ

readResponse Timeout after 5 secs.
Error: Unable to reset factory default
writing: ATE1

FATAL ERROR: HandleScope::HandleScope Entering the V8 API without proper locking in place
 1: 0xb7a940 node::Abort() [node]
 2: 0xa8e72f node::FatalError(char const*, char const*) [node]
 3: 0xd5c6aa v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: 0xd5dc0c v8::HandleScope::HandleScope(v8::Isolate*) [node]
 5: 0xb28b6a napi_open_handle_scope [node]
 6: 0x7f95a42185eb Poller::onData(uv_poll_s*, int, int) [/home/foureight84/projects/node-callattendant/node_modules/@serialport/bindings-cpp/prebuilds/linux-x64/node.napi.glibc.node]
 7: 0x16710a4  [node]
 8: 0x165f4ce uv_run [node]
 9: 0xabda6d node::SpinEventLoop(node::Environment*) [node]
10: 0xbc1164 node::NodeMainInstance::Run() [node]
11: 0xb35bc8 node::LoadSnapshotDataAndRun(node::SnapshotData const**, node::InitializationResult const*) [node]
12: 0xb3976f node::Start(int, char**) [node]
13: 0x7f95a796718a  [/lib/x86_64-linux-gnu/libc.so.6]
14: 0x7f95a7967245 __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
15: 0xabbdee _start [node]
Aborted

@ScreamZ
Copy link

ScreamZ commented Nov 15, 2023

Interested in this

@reconbot
Copy link
Member

We landed napi support and support workers as of 2 years ago.

@jsharf
Copy link

jsharf commented Apr 4, 2024

This still isn't working for me. I get the same error as this:

Doesn't look like it. I'm getting the same error:

npx ts-node src/index.ts 
Worker Received: test
Serial baud rate: 115200
Record duration: 60
writing: ATZ

readResponse Timeout after 5 secs.
Error: Unable to reset factory default
writing: ATE1

FATAL ERROR: HandleScope::HandleScope Entering the V8 API without proper locking in place
 1: 0xb7a940 node::Abort() [node]
 2: 0xa8e72f node::FatalError(char const*, char const*) [node]
 3: 0xd5c6aa v8::Utils::ReportApiFailure(char const*, char const*) [node]
 4: 0xd5dc0c v8::HandleScope::HandleScope(v8::Isolate*) [node]
 5: 0xb28b6a napi_open_handle_scope [node]
 6: 0x7f95a42185eb Poller::onData(uv_poll_s*, int, int) [/home/foureight84/projects/node-callattendant/node_modules/@serialport/bindings-cpp/prebuilds/linux-x64/node.napi.glibc.node]
 7: 0x16710a4  [node]
 8: 0x165f4ce uv_run [node]
 9: 0xabda6d node::SpinEventLoop(node::Environment*) [node]
10: 0xbc1164 node::NodeMainInstance::Run() [node]
11: 0xb35bc8 node::LoadSnapshotDataAndRun(node::SnapshotData const**, node::InitializationResult const*) [node]
12: 0xb3976f node::Start(int, char**) [node]
13: 0x7f95a796718a  [/lib/x86_64-linux-gnu/libc.so.6]
14: 0x7f95a7967245 __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
15: 0xabbdee _start [node]
Aborted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests