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

Attempting to close a serial port that had the "error" event raised results in 'Aborted' message and terminates Node #388

Closed
Analogreality opened this issue Sep 28, 2014 · 11 comments

Comments

@Analogreality
Copy link

I am having a problem recovering gracefully from a serial port disconnecting from the device's side.

Basically, I set up a connection to a device on a ARM Linux machine. I then do a .open() and connect. I send messages to the device and then receive them correctly. Good so far.

I then unplug the device.

The next time a .write() attempt is made to the device, it raises the "error" event.

However, after that, I wish to perform a reconnect.. so I attempt to close() the port. The text "Aborted." is written to the terminal and then the NodeJS instance dies, with no chance of recovery.

I want to be able to recover from this (or at least, not completely die).

Even having a process "unhandledException" global handler does not correctly recover this gracefully.

@bhaveshgohel
Copy link

Look into this issue #1468

I Tried the solution by @danyg, Working pretty well so far for:

    // clean exceptions from a previous load (refresh case)
    if(process._events.uncaughtException.length > 0){
        process._events.uncaughtException.splice(0,1);
    }
    process.on('uncaughtException', function(e){
        console.group('Node uncaughtException');
        if(!!e.message){
            console.log(e.message);
        }
        if(!!e.stack){
            console.log(e.stack);
        }
        console.log(e);
        console.groupEnd();
    });

    // Clean Buggy thing
    if(process._events.uncaughtException.length > 1 
        && !!process._events.uncaughtException[0].toString().match(/native code/)
    ){
        process._events.uncaughtException.splice(0,1);
    }

@Analogreality
Copy link
Author

Sorry.. I don't exactly know that can fix the problem... Just sort of catch/suppress the exception when it happens.

I don't know why it says it is unhandled.. Especially if I try to close the connection and explicitly had a .on("error", ... ) right before it.

I just think it is weird that a .close() method can crash hard like that.

@bhaveshgohel
Copy link

Any chances you can show some of the code or screenshots?

@Analogreality
Copy link
Author

when I attempt to close the port on my Raspberry Pi, the entire thread dies, writing "Aborted." to the console.

I don't have code with me at the moment, but I know it's acting the same way.

Is the desired behavior to kill the entire thread that the serial port is on?

@Analogreality
Copy link
Author

Yes, specifically on my Raspberry PI.. Raspbian ARM architecture.. it crashes hard when you attempt to .close() a serial port that has been unplugged physically.

Is there an alternative way of closing the open (but errored) port gracefully?

@Analogreality
Copy link
Author

Here is how to replicate:

Create a new SerialPort() specifying the Linux /dev/ttyS0 port. (successful)

Open the port. (successful)

UNPLUG THE PHYSICAL DEVICE

Send a message to the port (immediate callback, with err of failure)

In that callback OR on a timer later, perform a port.close() event

The port.close() method then terminates the thread, writing "Aborted" to console.

@bhaveshgohel
Copy link

Sorry, I don't have Raspberry pi at this moment.

But one thing that you are doing wrong is that, if the device is UNPLUG after creating new Serialport(), That means it's Already closed, then how can you close again ?

Second thing Specified the disconnected(Unplug) callback, so that you can know when the device is disconnected externally.

Here is the test code:

var com = require("serialport").SerialPort;
var msg = "Hello"; 
var comName = "/dev/ttyS0";
var _baudrate = 9600;

var port = new com(comName, {
         baudrate: _baudrate,
         "disconnectedCallback": function () {
         console.log("DEVICE: Disconnected.");
         //call the next function or whatever
        }
}, false);

port.open(function (error) {
    if(error){
        console.log(error);
        //Handle Error
    }

    else{  
        //start your coding from here
        port.write(msg, function(error, results) {
            if(error){
                console.log(error);
                //Handle Error
            }

            else{
                console.log("Write : " + msg);
                // uncomment below line to close the port internally after writing. 
                //port.close();                        
            }

        });

        port.on('data', function(data) {
            console.log("Read : " +  data);
        });
    }
});

port.on("close", function(){
    //this is called when you close the port internally 
    //or the device is unplug externally after connected.
    console.log("port Close");
});

port.on("error", function(error){
    console.log(error);
    //Handle Error
});

*If there are no typo then it should work. :)

@Analogreality
Copy link
Author

When I unplug the device, the underlying /Dev/ttyS0 object is removed and
is no longer available .. All write(function (err)) operations will fail
with err returned as 'cannot write io fail'. SerialPort does not clear
resources because it thinks it's still open.

So I attempt to close it manually.. Shouldn't it either gracefully ignore a
close request when called on a closed (or errored) device stream?

I mean at the very least it shouldn't terminate the calling thread's
process and write 'Aborted' to console.
On Oct 3, 2014 1:05 AM, "Bhavesh Gohel" [email protected] wrote:

Sorry, I don't have Raspberry pi at this moment.

But one thing that you are doing wrong is that, if the device is UNPLUG
after creating new Serialport(), That means it's Already closed, then how
can you close again ?

Second thing Specified the disconnected(Unplug) callback, so that you can
know when the device is disconnected externally.

Here is the test code:

var com = require("serialport").SerialPort;var msg = "Hello"; var comName = "/dev/ttyS0";var _baudrate = 9600;
var port = new com(comName, {
baudrate: _baudrate,
"disconnectedCallback": function () {
console.log("DEVICE: Disconnected.");
//call the next function or whatever
}}, false);
port.open(function (error) {
if(error){
console.log(error);
//Handle Error
}

else{
    //start your coding from here
    port.write(msg, function(error, results) {
        if(error){
            console.log(error);
            //Handle Error
        }

        else{
            console.log("Write : " + msg);
            // uncomment below line to close the port internally after writing.
            //port.close();
        }

    });

    port.on('data', function(data) {
        console.log("Read : " +  data);
    });
}});

port.on("close", function(){
//this is called when you close the port internally
//or the device is unplug externally after connected.
console.log("port Close");});
port.on("error", function(error){
console.log(error);
//Handle Error});

*If there are no typo then it should work. :)


Reply to this email directly or view it on GitHub
#388 (comment)
.

@bhaveshgohel
Copy link

Please check #393 I guess someone has fixed this bug for Linux.

@reconbot
Copy link
Member

Also track #702

@reconbot
Copy link
Member

reconbot commented Apr 3, 2016

I'm going to close this issue due to it's age, but if you'd like to continue with it feel free to reopen.

@reconbot reconbot closed this as completed Apr 3, 2016
@lock lock bot locked as resolved and limited conversation to collaborators May 6, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

No branches or pull requests

3 participants