plcpeople / nodeS7

Node.JS library for communication to Siemens S7 PLCs
MIT License
356 stars 120 forks source link

Error: write after end / Uncaught Exception #94

Open pelis opened 4 years ago

pelis commented 4 years ago

Hi, I have seen that this issue has been discussed already, however in my case it seems to relate to network issues: The connection seems to get interrupted from time to time. This Uncaught Exception/Crash happens about every once in a week, I am reading some 20 values every second. I am on nodeS7 release 0.3.4, on Windows 10. I am using this in node-red (my own node). Is there a chance to "catch" the error and fire an event or callback the read/write function with an error (other than true, so that this case could be handled accordingly)?

Here is the log:

2020.01.1617:16:48.444[2201920,473402219 IPC0725 S2] ISO-on-TCP Connection Confirm Packet Received 2020.01.16_17:16:48.710_16 Jan 17:16:48 - [red] Uncaught Exception: 2020.01.16_17:16:49.119_16 Jan 17:16:49 - Error: write after end 2020.01.1617:16:49.119 at writeAfterEnd (_stream_writable.js:236:12) 2020.01.1617:16:49.120 at Socket.Writable.write (_stream_writable.js:287:5) 2020.01.1617:16:49.121 at Socket.write (net.js:707:40) 2020.01.1617:16:49.151 at NodeS7.onISOConnectReply (C:\node_modules\node-red\node_modules\tlabs-nodes\node_modules\nodes7\nodeS7.js:341:17) 2020.01.1617:16:49.152 at Socket. (C:\node_modules\node-red\node_modules\tlabs-nodes\node_modules\nodes7\nodeS7.js:291:26) 2020.01.1617:16:49.153 at emitOne (events.js:116:13) 2020.01.1617:16:49.154 at Socket.emit (events.js:211:7) 2020.01.1617:16:49.155 at addChunk (_stream_readable.js:263:12) 2020.01.1617:16:49.155 at readableAddChunk (_stream_readable.js:250:11) 2020.01.1617:16:49.156 at Socket.Readable.push (_stream_readable.js:208:10) 2020.01.1617:16:49.157 at TCP.onread (net.js:597:20)

plcpeople commented 4 years ago

A lot has changed to do with reconnection since 0.3.4 - have you tried 0.3.10 to see if it solves this problem for you?

pelis commented 4 years ago

Thanks for your reply. No, I have not checked it - will do right away... What I have done: I have added a try/catch block in onISOConnectReply (see full code below). As of today the error has not returned (happens every once in a while)... So I will keep you updated.

modified code: NodeS7.prototype.onISOConnectReply = function (data) { var self = this; // PL: try catch *** !!!!!!!! try { self.isoclient.removeAllListeners('data'); //self.onISOConnectReply); self.isoclient.removeAllListeners('error');

    clearTimeout(self.connectTimeout);

    // ignore if we're not expecting it - prevents write after end exception as of #80
    if (self.isoConnectionState != 2) {
        outputLog('Ignoring ISO connect reply, expecting isoConnectionState of 2, is currently ' + self.isoConnectionState, 0, self.connectionID);
        return;
    }

    // Track the connection state
    self.isoConnectionState = 3;  // 3 = ISO-ON-TCP connected, Wait for PDU response.

    // Expected length is from packet sniffing - some applications may be different, especially using routing - not considered yet.
    if (data.readInt16BE(2) !== data.length || data.length < 22 || data[5] !== 0xd0 || data[4] !== (data.length - 5)) {
        outputLog('INVALID PACKET or CONNECTION REFUSED - DISCONNECTING');
        outputLog(data);
        outputLog('TPKT Length From Header is ' + data.readInt16BE(2) + ' and RCV buffer length is ' + data.length + ' and COTP length is ' + data.readUInt8(4) + ' and data[5] is ' + data[5]);
        self.connectionReset();
        return null;
    }

    outputLog('ISO-on-TCP Connection Confirm Packet Received', 0, self.connectionID);

    self.negotiatePDU.writeInt16BE(self.requestMaxParallel, 19);
    self.negotiatePDU.writeInt16BE(self.requestMaxParallel, 21);
    self.negotiatePDU.writeInt16BE(self.requestMaxPDU, 23);

    self.PDUTimeout = setTimeout(function () {
        self.packetTimeout.apply(self, arguments);
    }, self.globalTimeout, "PDU");

    self.isoclient.write(self.negotiatePDU.slice(0, 25));

} catch (ex) {
    if (self.connectCallback) {
        self.connectCallback(ex);
    }
    // this is a fatal error condition >> return
    return;
}
// PL: end try catch ******* !!!!!!!!

self.isoclient.on('data', function () {
    self.onPDUReply.apply(self, arguments);
});

self.isoclient.on('error', function () {
    self.readWriteError.apply(self, arguments);
});

}

plcpeople commented 4 years ago

OK hopefully it's solved in the latest version. Is anyone else seeing the same issue? It has always seemed strange that node would send data from a closed connection anyway.

pelis commented 4 years ago

I hope it goes away an also another Exception which, unfortunately, does not even show a qualified stack trace... - so I don't have a clue where to "catch" this one. I'll keep you updated.

2020.01.16_17:55:56.648_16 Jan 17:55:56 - [red] Uncaught Exception: 2020.01.16_17:55:56.649_16 Jan 17:55:56 - Error: read ECONNRESET 2020.01.1617:55:56.649 at _errnoException (util.js:992:11) 2020.01.1617:55:56.650 at TCP.onread (net.js:618:25) 2020.01.16_17:56:00.120_restarting...

plcpeople commented 4 years ago

That is strange, it's hard to even know if that's related to nodeS7.

pelis commented 4 years ago

It's really strange - I am trying to isolate it (only connecting to S7), now testing against 0.3.10...

flacohenao commented 4 years ago

It's really strange - I am trying to isolate it (only connecting to S7), now testing against 0.3.10...

Did you solve your problem using the 0.3.10?

ventr1x commented 4 years ago

No, that issue still exists. It appears extremely randomly, crashing the entire process, making this plugin completely useless for production. You can't even catch that exception because it's not being catched and bubbled up.

pelis commented 4 years ago

Sorry for my late response. I did not run into this crash after upgrading to 0.3.10. So for me, hopefully, it seems that the issue has gone away