From 2cab68f68f502bfa29169eeb3464cb0e532b3f2a Mon Sep 17 00:00:00 2001 From: Jonas Date: Mon, 11 Aug 2014 16:00:33 -0700 Subject: [PATCH] Merging fix for gh-369 Debug logging CLOEXEC and SYNC flags Stop polling before closing port. Better error message for polling error, propergate errors to disconnected callback trying to fix travis build for node 11 --- serialport.js | 38 +++++++++++++++++++++----------------- src/serialport.cpp | 1 + src/serialport_poller.cpp | 17 +++++++++++++---- src/serialport_poller.h | 2 ++ src/serialport_unix.cpp | 2 +- 5 files changed, 38 insertions(+), 22 deletions(-) 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) {