nitro icon indicating copy to clipboard operation
nitro copied to clipboard

Issue with `serialport` in dev

Open s3xysteak opened this issue 9 months ago • 7 comments

Environment

nitropack: latest compatibilityDate: "2025-03-04"

Node.js: v20.18.3

Reproduction

import { Buffer } from 'node:buffer'
import { SerialPort } from 'serialport'

export default defineNitroPlugin(() => {
  const port = new SerialPort({
    path: 'COM3',
    baudRate: 115200,
  })

  port
    .on('data', (data) => {
      console.log((data as Buffer).toString('utf-8'))
    })

  port.write(Buffer.from('Hi me!'))
})

When receive any data from serial (whatever using plugin or eventHandler), it will panic.

Describe the bug

When receiving data by using serialport, we have a error:

FATAL ERROR: HandleScope::HandleScope Entering the V8 API without proper locking in place

Error details
FATAL ERROR: HandleScope::HandleScope Entering the V8 API without proper locking in place
----- Native stack trace -----

 1: 00007FF6BA90738B node::SetCppgcReference+19771
 2: 00007FF6BA877DF9 node::OnFatalError+265
 3: 00007FF6BB2E5929 v8::HandleScope::Initialize+137
 4: 00007FF6BB2CDC2E v8::HandleScope::HandleScope+14
 5: 00007FF6BA8CF99A napi_open_handle_scope+154
 6: 00007FFA3677A0E0 napi_register_module_v1+9744
 7: 00007FF6BA96CD2B uv_update_time+491
 8: 00007FF6BA96C8A4 uv_run+900
 9: 00007FF6BA93D7A5 node::SpinEventLoop+405
10: 00007FF6BA824392 OSSL_STORE_LOADER_get0_description+153698
11: 00007FF6BA8BB26D node::Start+4957
12: 00007FF6BA8B9F40 node::Start+48
13: 00007FF6BA66D9BC AES_cbc_encrypt+151532
14: 00007FF6BBB0848C inflateValidate+19196
15: 00007FFA6BC97374 BaseThreadInitThunk+20
16: 00007FFA6D13CC91 RtlUserThreadStart+33
FATAL ERROR: v8::HandleScope::CreateHandle() Cannot create a handle without a HandleScope
----- Native stack trace -----

 1: 00007FF6BA90738B void __cdecl node::SetCppgcReference(class v8::Isolate * __ptr64,class v8::Local<class v8::Object>,void * __ptr64)+19771
 2: 00007FF6BA877DF9 void __cdecl node::OnFatalError(char const * __ptr64,char const * __ptr64)+265
 3: 00007FF6BB2F162B public: void __cdecl v8::FunctionTemplate::RemovePrototype(void) __ptr64+331
 4: 00007FF6BB187896 public: struct v8::WrapperDescriptor __cdecl v8::CppHeap::wrapper_descriptor(void)const __ptr64+64918
 5: 00007FF6BB2CDB24 public: __cdecl v8::EscapableHandleScope::EscapableHandleScope(class v8::Isolate * __ptr64) __ptr64+52
 6: 00007FF6BA876E69 DSA_meth_get_flags+89289
 7: 00007FF6BA9072A2 void __cdecl node::SetCppgcReference(class v8::Isolate * __ptr64,class v8::Local<class v8::Object>,void * __ptr64)+19538
 8: 00007FF6BA877E0B void __cdecl node::OnFatalError(char const * __ptr64,char const * __ptr64)+283
 9: 00007FF6BB2E5929 protected: void __cdecl v8::HandleScope::Initialize(class v8::Isolate * __ptr64) __ptr64+137
11: 00007FF6BA8CF99A napi_open_handle_scope+154
12: 00007FFA3677A0E0 napi_register_module_v1+9744
13: 00007FF6BA96CD2B uv_update_time+491
14: 00007FF6BA96C8A4 uv_run+900
15: 00007FF6BA93D7A5 class v8::Maybe<int> __cdecl node::SpinEventLoop(class node::Environment * __ptr64)+405
16: 00007FF6BA824392 X509_STORE_get_cleanup+153698
17: 00007FF6BA8BB26D int __cdecl node::Start(int,char * __ptr64 * __ptr64 const)+4957
18: 00007FF6BA8B9F40 int __cdecl node::Start(int,char * __ptr64 * __ptr64 const)+48
19: 00007FF6BA66D9BC AES_cbc_encrypt+151532
20: 00007FF6BBB0848C inflateValidate+19196
21: 00007FFA6BC97374 BaseThreadInitThunk+20
22: 00007FFA6D13CC91 RtlUserThreadStart+33
 ELIFECYCLE  Command failed with exit code 134.

Additional context

serialport is a js lib based on nodejs, which is usually used for serial communication.

The repro code above works well if using node xxx.mjs to boot it. So I guess maybe I cannot use serialport or even Node.js in Nitro directly like this?

s3xysteak avatar Mar 04 '25 07:03 s3xysteak

It seems an issue with Node.js worker threads (that runs isolated code) and serialport library. (I expect nitro production build works)

Can you try using devHandlers ?

pi0 avatar Mar 04 '25 12:03 pi0

As your expect, nitro production build and devHandlers both work. Is that possible to make it work without devHandlers?

s3xysteak avatar Mar 04 '25 12:03 s3xysteak

We need to investigate what is the issue with serialport or Node.js/v8.

We might support alternative runner for Nitro dev server (to use full Node.js process which is slower) in future releases but nothing is immediately fixable.

pi0 avatar Mar 04 '25 12:03 pi0

Thanks for the quick feedback!

but nothing is immediately fixable

That said, I'm still glad to know that this will be improved in the future. At least for now this isn't completely unusable.

// routes/foo.ts
export default defineEventHandler()

// nitro.config
import foo from './src/routes/foo'

devHandlers: [
  {
    route: '/'
    handler: foo
  }
]

This works as expected, the problem is that then routes/foo.ts can't use auto-improt. This is not unacceptable, but I'd like to be able to turn off code hints for auto-import in this file, I wonder if there's a setting for that?

// routes/foo.ts Maybe like:
// ts-disable-something
import { defineEventHandler } from 'h3'

export default defineEventHandler()

s3xysteak avatar Mar 05 '25 05:03 s3xysteak

We have the same issue using confluentinc/confluent-kafka-javascript which uses librdkafka under the hood.

DrJume avatar Apr 19 '25 18:04 DrJume

The serialport cannot work in worker threads, as reported here: https://github.com/serialport/node-serialport/issues/2748

We might support alternative runner for Nitro dev server (to use full Node.js process which is slower) in future releases but nothing is immediately fixable.

Until this is supported, you might need to track serialport's progress on this issue.

kricsleo avatar Apr 29 '25 09:04 kricsleo

Hey! I'm running into a similar issue with JCMais/node-libcurl Could this be happening because nitro encapsulates routes inside worker processes??

FATAL ERROR: v8::HandleScope::CreateHandle() Cannot create a handle without a HandleScope
----- Native stack trace -----

 1: 0xe19ca5 node::OnFatalError(char const*, char const*) [node]
 2: 0x123f996 v8::Utils::ReportApiFailure(char const*, char const*) [node]
 3: 0x13ec8ba v8::internal::HandleScope::Extend(v8::internal::Isolate*) [node]
 4: 0x1254da0 v8::Object::GetCreationContextChecked() [node]
 5: 0xe720ba node::MakeCallback(v8::Isolate*, v8::Local<v8::Object>, v8::Local<v8::Function>, int, v8::Local<v8::Value>*, node::async_context) [node]
 6: 0x7efb54c42016 NodeLibcurl::Easy::OnHeader(char*, unsigned long, unsigned long)
....

gokaybiz avatar Sep 30 '25 04:09 gokaybiz