serialport / bindings-cpp

The C++ bindings for the node serialport project.
MIT License
19 stars 39 forks source link

Recursion+memory leak in unixRead() #162

Open dyarkovoy opened 9 months ago

dyarkovoy commented 9 months ago

SerialPort Bindings Version

12.0.1

Node Version

v21.2.0

Electron Version

No response

Platform

Linux opi5b 5.10.110-rockchip-rk3588 #1.0.2 SMP Thu Apr 13 16:55:55 CST 2023 aarch64 GNU/Linux

Architecture

arm64

Hardware or chipset of serialport

16550A

What steps will reproduce the bug?

Simply opening /dev/ttyS9 on this hardware using the code below:

const debug=require('debug') debug.enable('*') const { SerialPort } = require('serialport') const port = new SerialPort({ path: '/dev/ttyS9', baudRate: 57600, })

port.on('data', function (data) { console.log('Data:', data) })

What happens?

initial unixRead() that is called on port open is trapped into recursive call to itself, because readAsync() always returns { bytesRead:0 }, see https://github.com/serialport/bindings-cpp/blob/39fd4be0904434a0ec72ee88e04d54bfa1645667/lib/unix-read.ts#L41C1-L44C1

The debug log confirms the said:

2023-11-26T14:55:04.624Z serialport/bindings-cpp loading LinuxBinding 2023-11-26T14:55:04.626Z serialport/stream opening path: /dev/ttyS9 2023-11-26T14:55:04.626Z serialport/bindings-cpp open 2023-11-26T14:55:04.628Z serialport/stream _read queueing _read for after open 2023-11-26T14:55:04.629Z serialport/bindings-cpp/poller Creating poller 2023-11-26T14:55:04.629Z serialport/stream opened path: /dev/ttyS9 2023-11-26T14:55:04.629Z serialport/stream _read reading { start: 0, toRead: 65536 } 2023-11-26T14:55:04.631Z serialport/bindings-cpp read 2023-11-26T14:55:04.631Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.632Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.632Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.632Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.632Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.633Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.633Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.633Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.633Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.633Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.634Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.634Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.634Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.634Z serialport/bindings-cpp/unixRead Starting read 2023-11-26T14:55:04.634Z serialport/bindings-cpp/unixRead Starting read

... and continues indefinitely

What should have happened?

unixRead() should return normally or throw

Additional information

I realize this is probably buggy hardware, but is it possible to work around this by implementing a simple recursion counter and throw if recursion deph exceeds 10 or so, for example?

Kiliar commented 2 months ago

Faced the same issue. My solution was just to refactor unixRead() from recursion to simple while (true) {} and adding some delay in that loop. That solved both high cpu usage & "memory leak"