diff --git a/serialport.js b/serialport.js index fefdca131c..4ce025c700 100644 --- a/serialport.js +++ b/serialport.js @@ -149,11 +149,13 @@ function SerialPortFactory() { options.parser(self, data); }; - options.disconnectedCallback = options.disconnectedCallback || function () { + options.disconnectedCallback = options.disconnectedCallback || function (err) { if (self.closing) { return; } - var err = new Error("Disconnected"); + if(!err) { + err = new Error("Disconnected"); + } self.emit("disconnect",err); }; @@ -200,7 +202,7 @@ function SerialPortFactory() { if(!err) { self._read(); } else { - self.disconnected(); + self.disconnected(err); } }); self.serialPoller.start(); @@ -274,10 +276,9 @@ function SerialPortFactory() { self.serialPoller.start(); } } else if (err.code && (err.code === "EBADF" || err.code === 'ENXIO' || (err.errno===-1 || err.code === 'UNKNOWN'))) { // handle edge case were mac/unix doesn't clearly know the error. - self.disconnected(); + self.disconnected(err); } else { self.fd = null; - // console.log("afterRead"); self.emit('error', err); self.readable = false; } @@ -351,15 +352,15 @@ function SerialPortFactory() { } // if !'win32' - SerialPort.prototype.disconnected = function (callback) { + SerialPort.prototype.disconnected = function (err) { var self = this; var fd = self.fd; // send notification of disconnect if (self.options.disconnectedCallback) { - self.options.disconnectedCallback(); + self.options.disconnectedCallback(err); } else { - self.emit("disconnect"); + self.emit("disconnect", err); } self.paused = true; self.closing = true; @@ -371,7 +372,11 @@ function SerialPortFactory() { try { factory.SerialPortBinding.close(fd, function (err) { - console.log('Disconnect completed' + (err ? ' with error' : ''), err); + if(err) { + console.log('Disconnect completed with error:' + err); + } else { + console.log('Disconnect completed'); + } }); } catch (e) { console.log('Disconnect failed with exception', e); @@ -386,9 +391,6 @@ function SerialPortFactory() { self.serialPoller.close(); } - if (callback) { - callback(); - } }; @@ -412,6 +414,13 @@ function SerialPortFactory() { } self.closing = true; + + // Stop polling before closing the port. + if (process.platform !== 'win32') { + self.readable = false; + self.serialPoller.close(); + } + try { factory.SerialPortBinding.close(fd, function (err) { @@ -430,11 +439,6 @@ function SerialPortFactory() { self.closing = false; self.fd = 0; - if (process.platform !== 'win32') { - self.readable = false; - self.serialPoller.close(); - } - if (callback) { callback(); } diff --git a/src/serialport.cpp b/src/serialport.cpp index 26837e50bb..083f4b8747 100644 --- a/src/serialport.cpp +++ b/src/serialport.cpp @@ -165,6 +165,7 @@ void EIO_AfterWrite(uv_work_t* req) { // We're not done with this baton, so throw it right back onto the queue. // Don't re-push the write in the event loop if there was an error; because same error could occur again! // TODO: Add a uv_poll here for unix... + fprintf(stderr, "Write again...\n"); uv_queue_work(uv_default_loop(), req, EIO_Write, (uv_after_work_cb)EIO_AfterWrite); return; } diff --git a/src/serialport_poller.cpp b/src/serialport_poller.cpp index 50e318a75b..29150ed079 100644 --- a/src/serialport_poller.cpp +++ b/src/serialport_poller.cpp @@ -16,10 +16,10 @@ SerialportPoller::~SerialportPoller() { }; void _serialportReadable(uv_poll_t *req, int status, int events) { - SerialportPoller* obj = (SerialportPoller*) req->data; + SerialportPoller* sp = (SerialportPoller*) req->data; // We can stop polling until we have read all of the data... - obj->_stop(); - obj->callCallback(status); + sp->_stop(); + sp->callCallback(status); } void SerialportPoller::callCallback(int status) { @@ -29,7 +29,16 @@ void SerialportPoller::callCallback(int status) { v8::Handle argv[1]; if(status != 0) { - argv[0] = v8::Exception::Error(NanNew("polling error")); + // error handling changed in libuv, see: + // https://github.com/joyent/libuv/commit/3ee4d3f183331 + #ifdef UV_ERRNO_H_ + const char* err_string = uv_strerror(status); + #else + uv_err_t errno = uv_last_error(uv_default_loop()); + const char* err_string = uv_strerror(errno); + #endif + snprintf(this->errorString, sizeof(this->errorString), "Error %s on polling", err_string); + argv[0] = v8::Exception::Error(NanNew(this->errorString)); } else { argv[0] = NanUndefined(); } diff --git a/src/serialport_poller.h b/src/serialport_poller.h index 09f9afe2da..664afd4c3a 100644 --- a/src/serialport_poller.h +++ b/src/serialport_poller.h @@ -6,6 +6,7 @@ #define SERIALPORT_POLLER_H #include +#include "serialport.h" class SerialportPoller : public node::ObjectWrap { public: @@ -26,6 +27,7 @@ class SerialportPoller : public node::ObjectWrap { uv_poll_t poll_handle_; int fd_; + char errorString[ERROR_STRING_SIZE]; NanCallback* callback_; }; diff --git a/src/serialport_unix.cpp b/src/serialport_unix.cpp index 16aabc63ca..42a52b29f0 100644 --- a/src/serialport_unix.cpp +++ b/src/serialport_unix.cpp @@ -126,7 +126,7 @@ void EIO_Open(uv_work_t* req) { } - int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK); + int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC); int fd = open(data->path, flags); if (fd == -1) {