serialport/node-serialport

serialport/bindings-cpp/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read]

semireg opened this issue · 1 comments

SerialPort Version

Tested 10-12

Node Version

Electron main

Electron Version

Tested 26-30

Platform

Sonoma 14.14.1 - Darwin Kernel Version 23.4.0 macOS

Architecture

ARM

Hardware or chipset of serialport

FTDI FT232R USB UART (PID: 0x6001)

What steps will reproduce the bug?

I have a weight scale that responds to a simple "W\r\n". This works fine using screen /dev/tty.usbserial-AI04V9SR 9600, here's the expected output:

CleanShot 2024-04-19 at 10 55 13

I'm no stranger to USB devices, Electron, native modules, TypeScript, etc. I'm unable to get serialport to work as I'd expect.

What happens?

Here's the output from electron 26.6.9 main when DEBUG=*

  serialport/bindings-cpp list +0ms
  serialport/stream opening path: /dev/tty.usbserial-AI04V9SR +0ms
  serialport/bindings-cpp open +1ms
  serialport/stream _read queueing _read for after open +0ms
  serialport/bindings-cpp/poller Creating poller +0ms
  serialport/stream opened path: /dev/tty.usbserial-AI04V9SR +27ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +0ms
  serialport/bindings-cpp read +27ms
  serialport/bindings-cpp/unixRead Starting read +0ms
10:50:45.861 ›   28 | ScaleManager opening path /dev/tty.usbserial-AI04V9SR
  serialport/bindings-cpp/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -35,
  code: 'EAGAIN',
  syscall: 'read'
} +0ms
  serialport/bindings-cpp/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings-cpp/poller Polling for "readable" +1ms
  serialport/bindings-cpp list +2s
10:50:47.841 ›    3 | ScaleManager write (AI04V9SR at path /dev/tty.usbserial-AI04V9SR): W

  serialport/stream _write 3 bytes of data +2s
  serialport/bindings-cpp write 3 bytes +4ms
  serialport/bindings-cpp/unixWrite Starting write 3 bytes offset 0 bytesToWrite 3 +0ms
...

My calling code is fairly vanilla. I've tried with autoOpen:true/false, with/without a parser. Here's a code sample:

            const port = new SerialPort({ path, baudRate: 9600, autoOpen: false });
            port.open((openError) => {
              log.info(`ScaleManager opening path ${path}`);
              if (openError) {
                log.error(`ScaleManager portInfo:${JSON.stringify(portInfo)} openError:${openError}`);
                return;
              }
              deviceWrapper.ready = true;
            });

            const newParser = port.pipe(new InterByteTimeoutParser({ interval: 50 }));
            newParser.on('data', (data: Buffer) => {
              log.info('Data:', data);
            });

My writing looks like:

port.write(Buffer.from('W\r\n'), 'utf-8', (writeError) => {
                  if (writeError) {
                    log.error(`ScaleManager writeError:${writeError}`);
                    port.close();
                  }
                });

My goal is to keep targeting Electron 26 due to macOS 10.13/10.14, along with other native module compatibility.

Here's the DEBUG repl using node v18.17.1.

% DEBUG=serialport* npx @serialport/repl /dev/tty.usbserial-AI04V9SR
  serialport/bindings-cpp loading DarwinBinding +0ms
DEBUG=serialport* # enable debugging with DEBUG=serialport*
port = SerialPort({ path: "/dev/tty.usbserial-AI04V9SR", baudRate: 9600, autoOpen: false })
globals { SerialPort, SerialPortMock, path, port }
> port.open()
  serialport/stream opening path: /dev/tty.usbserial-AI04V9SR +0ms
  serialport/bindings-cpp open +0ms
undefined
>   serialport/bindings-cpp/poller Creating poller +0ms
  serialport/stream opened path: /dev/tty.usbserial-AI04V9SR +30ms

undefined
> port.write('W\r\n');
  serialport/stream _write 3 bytes of data +7s
  serialport/bindings-cpp write 3 bytes +7s
  serialport/bindings-cpp/unixWrite Starting write 3 bytes offset 0 bytesToWrite 3 +0ms
true
>   serialport/bindings-cpp/unixWrite write returned: wrote 3 bytes +1ms
  serialport/bindings-cpp/unixWrite Finished writing 3 bytes +0ms
  serialport/stream binding.write write finished +2ms

undefined
> port.read()
  serialport/stream _read reading { start: 0, toRead: 65536 } +3s
  serialport/bindings-cpp read +3s
  serialport/bindings-cpp/unixRead Starting read +0ms
null
>   serialport/bindings-cpp/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -35,
  code: 'EAGAIN',
  syscall: 'read'
} +1ms
  serialport/bindings-cpp/unixRead waiting for readable because of code: EAGAIN +0ms
  serialport/bindings-cpp/poller Polling for "readable" +11s

undefined

Immediately after this I can type screen /dev/tty.usbserial-AI04V9SR 9600 and press W and receive a response from the scale.

Oh, and here's the stty/permission settings.

% ls -lah /dev/tty.usbserial-AI04V9SR    
crw-rw-rw-  1 root  wheel  0x9000002 Apr 19 11:07 /dev/tty.usbserial-AI04V9SR

% stty -a -f /dev/tty.usbserial-AI04V9SR
speed 9600 baud; 0 rows; 0 columns;
lflags: -icanon -isig -iexten -echo -echoe -echok -echoke -echonl
	-echoctl -echoprt -altwerase -noflsh -tostop -flusho -pendin
	-nokerninfo -extproc
iflags: -istrip -icrnl -inlcr -igncr -ixon -ixoff -ixany -imaxbel -iutf8
	-ignbrk -brkint -inpck -ignpar -parmrk
oflags: -opost -onlcr -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
	-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = <undef>;
	eol2 = <undef>; erase = ^?; intr = ^C; kill = ^U; lnext = ^V;
	min = 1; quit = ^\; reprint = ^R; start = ^Q; status = ^T;
	stop = ^S; susp = ^Z; time = 0; werase = ^W;

What should have happened?

I'd just like to see the output of the weight scale.

Additional information

I've unplug/replugged the USB device multiple times to ensure it's a clean/fresh interface. No difference, unfortunately.

I have the same issue, with similar scenario. I'm running archlinux with electron 26.2.1 serialport v12
I can successfully read from serial when running in debug mode via phpstrom debug, but it fails to run in development or production mode.

dev mode output:

serialport/stream opening path: /dev/ttyACM0 +0ms
serialport/bindings-cpp open +2s
serialport/stream _read queueing _read for after open +2ms
serialport/bindings-cpp/poller Creating poller +0ms
serialport/stream opened path: /dev/ttyACM0 +187ms
serialport/stream _write 18 bytes of data +0ms
serialport/bindings-cpp write 18 bytes +189ms
serialport/bindings-cpp/unixWrite Starting write 18 bytes offset 0 bytesToWrite 18 +0ms
serialport/stream _read reading { start: 0, toRead: 65536 } +0ms
serialport/bindings-cpp read +1ms
serialport/bindings-cpp/unixRead Starting read +0ms
serialport/bindings-cpp/unixWrite write returned: wrote 18 bytes +1ms
serialport/bindings-cpp/unixWrite Finished writing 18 bytes +0ms
serialport/stream binding.write write finished +1ms
message written
serialport/bindings-cpp/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
errno: -11,
code: 'EAGAIN',
syscall: 'read'
} +0ms
serialport/bindings-cpp/unixRead waiting for readable because of code: EAGAIN +0ms
serialport/bindings-cpp/poller Polling for "readable" +3ms

With debug enabled

  serialport/stream opening path: /dev/ttyACM0 +0ms
  serialport/bindings-cpp open +6s
  serialport/stream _read queueing _read for after open +2s
  serialport/bindings-cpp/poller Creating poller +0ms
  serialport/stream opened path: /dev/ttyACM0 +1ms
  serialport/stream _write 18 bytes of data +0ms
  serialport/bindings-cpp write 18 bytes +2s
  serialport/bindings-cpp/unixWrite Starting write 18 bytes offset 0 bytesToWrite 18 +0ms
  serialport/stream _read reading { start: 0, toRead: 65536 } +1ms
  serialport/bindings-cpp read +0ms
  serialport/bindings-cpp/unixRead Starting read +0ms
  serialport/bindings-cpp/unixWrite write returned: wrote 18 bytes +3ms
  serialport/bindings-cpp/unixWrite Finished writing 18 bytes +1ms
  serialport/stream binding.write write finished +4ms
  serialport/bindings-cpp/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -11,
  code: 'EAGAIN',
  syscall: 'read'
} +1s
  serialport/bindings-cpp/unixRead waiting for readable because of code: EAGAIN +1ms
  serialport/bindings-cpp/poller Polling for "readable" +1s
  serialport/bindings-cpp/poller received "readable" +2ms
  serialport/bindings-cpp/unixRead Starting read +3ms
  serialport/bindings-cpp/unixRead Finished read 29 bytes +0ms
  serialport/stream binding.read finished { bytesRead: 29 } +1s
  serialport/stream _read reading { start: 29, toRead: 65507 } +8s
  serialport/bindings-cpp read +10s
  serialport/bindings-cpp/unixRead Starting read +8s
  serialport/stream #close +6s
  serialport/bindings-cpp close +6s
  serialport/bindings-cpp/poller Stopping poller +14s
  serialport/bindings-cpp/poller Destroying poller +0ms
Data2: <Buffer 52 65 63 65 69 76 65 64 3a 20 50 52 4f 56 41 20 50 52 4f 56 41 20 50 52 4f 56 41 0d 0a>
Readable Buffer: <Buffer 52 65 63 65 69 76 65 64 3a 20 50 52 4f 56 41 20 50 52 4f 56 41 20 50 52 4f 56 41 0d 0a>
  serialport/bindings-cpp/unixRead read error [Error: EAGAIN: resource temporarily unavailable, read] {
  errno: -11,
  code: 'EAGAIN',
  syscall: 'read'
} +6s
  serialport/stream binding.read error BindingsError: Port is not open
    at unixRead (/home/thepasto/workspace/IRIDE/electron-iwcassa2/release/app/node_modules/@serialport/bindings-cpp/dist/unix-read.js:38:23) {
  canceled: true
} +7ms
  serialport/stream _read queueing _read for after open +0ms
  serialport/stream binding.close finished +56ms

Any clue?
If you need more, just ask.

Thanks