Coder Social home page Coder Social logo

Comments (17)

cleoo avatar cleoo commented on September 27, 2024 1

The problem seems to come from a nodejs dependency. Versions higher than 20.2 have the defect. I got around the difficulty by downgrading all my installations to v20.2.0

from node-serialport.

robertsLando avatar robertsLando commented on September 27, 2024 1

Having the same problem with version 12.0.0 NodeJS 20.8.0. Simple repro script:

import { SerialPort } from 'serialport'

let port: SerialPort

function open() {
	const path = '/dev/ttyUSB0'

	if (!port) {
		port = new SerialPort({
			path,
			baudRate: 9600,
			dataBits: 8,
			parity: 'none',
			stopBits: 1,
			autoOpen: false
		})

		port.on('error', err => {
			console.log('Error: ', err.message)
		})

		port.on('close', () => {
			console.log('Port closed')
		})

		port.on('open', () => {
			console.log('Port opened')
		})

		// THIS CAUSES THE ERROR
		port.on('data', data => {
			console.log('Data: ', data)
		})
	}

	port.open(err => {
		if (err) {
			return console.log('Error opening port: ', err.message)
		}

		setTimeout(() => {
			close()
		}, 3000)
	})
}

function close() {
	port.close(err => {
		if (err) {
			return console.log('Error closing port: ', err.message)
		}

		setTimeout(() => {
			open()
		}, 3000)
	})
}

open()

I discovered that by removing the port.on('data') listener the port is able to reconnect correctly, with that event listener I always get the error above: Error Resource temporarily unavailable Cannot lock port

cc @reconbot @GazHank

from node-serialport.

devwatts avatar devwatts commented on September 27, 2024

Were you able to fix this issue?

from node-serialport.

devwatts avatar devwatts commented on September 27, 2024

I am running raspbian on a pi 3

Getting the same issue on node 18

from node-serialport.

robertsLando avatar robertsLando commented on September 27, 2024

Seems NodeJS 18.19.0 (latest now) WORKS but 20.11.0 (latest now) still doesn't.

from node-serialport.

Theiremi avatar Theiremi commented on September 27, 2024

I encounter the same problem in my program and made some discoveries by executing the code of @robertsLando with debug flags.
Here are the output I got in different scenarios :

  • With port.on('data') :
  serialport/stream _read queueing _read for after open +2ms
  serialport/stream opened path: /dev/ttyUSB0 +13ms
Port opened
  serialport/stream _read reading { start: 0, toRead: 65536 } +1ms
  serialport/stream binding.read finished { bytesRead: 1 } +908ms
Data:  <Buffer fa>
  serialport/stream _read reading { start: 1, toRead: 65535 } +1ms
  serialport/stream #close +2s
  serialport/stream binding.close finished +0ms
Port closed
  serialport/stream opening path: /dev/ttyUSB0 +3s
  serialport/stream Binding #open had an error [Error: Error Resource temporarily unavailable Cannot lock port] +1ms
Error opening port:  Error Resource temporarily unavailable Cannot lock port
  • Without port.on('data') :
  serialport/stream opened path: /dev/ttyUSB0 +11ms
Port opened
  serialport/stream #close +3s
  serialport/stream binding.close finished +1ms
Port closed
  serialport/stream opening path: /dev/ttyUSB0 +3s
  serialport/stream opened path: /dev/ttyUSB0 +9ms
Port opened
  • Keeping port.on('data') but removing the delay between opening and closing :
  serialport/stream _read queueing _read for after open +1ms
  serialport/stream opened path: /dev/ttyUSB0 +9ms
Port opened
  serialport/stream _read reading { start: 0, toRead: 65536 } +1ms
  serialport/stream #close +3ms
  serialport/stream binding.close finished +1ms
Port closed
  serialport/stream binding.read finished { bytesRead: 1 } +907ms
Data:  <Buffer f8>
  serialport/stream _read queueing _read for after open +2ms
  serialport/stream opening path: /dev/ttyUSB0 +2s
  serialport/stream opened path: /dev/ttyUSB0 +10ms
Port opened

In the first output logs, it seems like :

  1. SerialPort tries to read data from the port (serialport/stream _read reading { start: 0, toRead: 65536 })
  2. Succesfully read data (serialport/stream binding.read finished { bytesRead: 1 })
  3. Tries to read more data (serialport/stream _read reading { start: 1, toRead: 65535 })
  4. Never stop waiting for new data even after closing the port

I tested with a device continuously sending data, and the problem haven't ocurred.
In the last scenario, the port is probably closed before receiving the data, so SerialPort doesn't try to listen again for new data, and the port is completely free.

Hope this can help to solve the issue !

from node-serialport.

DasSamsi avatar DasSamsi commented on September 27, 2024

I had the same problem on Node v20.10.0.

I debugged 8+ hours with this simple Code:

import {SerialPort} from "serialport";

async function main() {

    console.time();

    let serialPort = new SerialPort({
        path: '/dev/ttyS0',
        baudRate: 9600,
        autoOpen: false
    });

    serialPort.on("data", (data) => {
        console.log("Data received: " + data);
    });

    try {
        for (let i = 0; i < 3; i++) {

            //OPEN
            console.timeLog('default', 'open');
            await new Promise((resolve, reject) => {
                if (!serialPort.isOpen) serialPort.open((err) => {
                    if (err) return reject(err);
                    console.timeLog('default', 'serialPort opened');
                    return resolve();
                });
            });

            await new Promise((resolve) => setTimeout(() => resolve(), 200));

            //WRITE
            console.timeLog('default', 'write');
            await new Promise((resolve, reject) => {

                if (serialPort.isOpen) serialPort.write('0010000202=?097\r', (err) => {
                    if (err) return reject(err);
                    console.timeLog('default', 'serialPort written');
                    return resolve();
                });
            });

            await new Promise((resolve) => setTimeout(() => resolve(), 200));

            //CLOSE
            console.timeLog('default', 'close');
            await new Promise((resolve, reject) => {
                if (serialPort.isOpen) serialPort.close((err) => {
                    if (err) return reject(err);
                    console.timeLog('default', 'serialPort closed');
                    return resolve();
                });
            });

            await new Promise((resolve) => setTimeout(() => resolve(), 200));
        }
    } catch (err) {
        console.error(err);

        // end the process
        process.exit(1);
    }
}

await main();

The solution for me was to upgrade Node to Version v21+ (v21.6.2). On 21+ it works like a dream and without clear the "data" listener!

from node-serialport.

Theiremi avatar Theiremi commented on September 27, 2024

Thank you @DasSamsi for your return !
Just tested on my side and cannot reproduce the bug with node V21.6.2

from node-serialport.

stknob avatar stknob commented on September 27, 2024

This seems to have been recently fixed in node 20.11.1 and 21.6.2 (i just tested a bunch of versions using @DasSamsi's reproducer), as everything prior to 21.6.2 is broken too.

from node-serialport.

stknob avatar stknob commented on September 27, 2024

The root cause seems to be related to libuv using io_uring in 20.11.0 and 21.6.1, which has been disabled in the newer node / libuv versions (node-v21.6.2/deps/uv update from 1.47.0 to 1.48.0):

$ grep ttyUSB node-v21.6.1.log  -A1
437242 openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK|O_SYNC|O_CLOEXEC <unfinished ...>
437232 io_uring_enter(37, 2, 2, IORING_ENTER_GETEVENTS, NULL, 0) = 2

vs.

$ grep ttyUSB node-v21.6.2.log  -A1
437288 openat(AT_FDCWD, "/dev/ttyUSB0", O_RDWR|O_NOCTTY|O_NONBLOCK|O_SYNC|O_CLOEXEC <unfinished ...>
437281 epoll_ctl(31, EPOLL_CTL_ADD, 32, {events=EPOLLIN, data={u32=32, u64=32}}) = 0

UPDATE: First broken version is Node 20.3.0, which updates libuv to 1.45.0:
nodejs/node@bfcb3d1d9a

UPDATE #2: Libuv 1.48.0 update is unrelated, NodeJS commit that disabled io_uring by default (to fix the CVE-2024-22017 setuid() issue): nodejs/node@686da19abb

from node-serialport.

robertsLando avatar robertsLando commented on September 27, 2024

@stknob Thanks for the reference, so this should work for every (latest) nodejs version as of today

from node-serialport.

fcapano avatar fcapano commented on September 27, 2024

I can still reproduce this bug in Arch Linux using NodeJs v21.6.2, serialport 12.0.0, and libuv 1.48.0,

from node-serialport.

stknob avatar stknob commented on September 27, 2024

I can still reproduce this bug in Arch Linux using NodeJs v21.6.2, serialport 12.0.0, and libuv 1.48.0,

@fcapano Does Arch set the UV_USE_IO_URING=1 environment variable somewhere?

from node-serialport.

fcapano avatar fcapano commented on September 27, 2024

@stknob no, doesn't look like it's set.
But if I export UV_USE_IO_URING=0 before running the node server, I'm able to open/close/reopen ports. Thanks for the pointer!

from node-serialport.

CorpusCallosum avatar CorpusCallosum commented on September 27, 2024

Hello, I'm running Node v22.1.0, and still getting this error in my Electron app, when running in dev mode. Every time I make a change in my app and recompile - I'm getting this error:

Uncaught (in promise) Error: Error Resource temporarily unavailable Cannot lock port

Only way to fix it is to quit the app and relaunch in dev mode.

Any ideas how to fix this?

from node-serialport.

CorpusCallosum avatar CorpusCallosum commented on September 27, 2024

UV_USE_IO_URING=0

But if I export UV_USE_IO_URING=0 before running the node server, I'm able to open/close/reopen ports. Thanks for the pointer!

Hey @fcapano - could you please clarify? How do I go about exporting this environment variable? Thanks!

from node-serialport.

wwwmomo avatar wwwmomo commented on September 27, 2024
new SerialPort({
            path: device.name,
            baudRate: device.rate, 
            dataBits: device.data, 
            stopBits: device.stop, 
            parity: 'None',
            flowControl: 'None',
            autoOpen: false,
            lock: false   //try set lock to false
 },  (err) => {
            console.log(err, 'new err')
})

try set lock to false

from node-serialport.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.