From 71c0d4ea305c39198e318629ae71c705dac2c096 Mon Sep 17 00:00:00 2001 From: Jason Curl Date: Mon, 1 May 2017 12:47:48 +0200 Subject: [PATCH] Treat EINTR as a non-fatal interrupt If a signal occurs for whatever reason, the OS may return EINTR as an error code. This was being treated as a fatal error in the .NET implementation. libnserial now returns zero for serial_read and serial_write as is the case for EAGAIN / EWOULDBLOCK. The .NET code was optimized slightly so that in case zero is returned, it skips a buffer check and tries again (this change is non-functional). Issue: DOTNET-91 --- code/Native/UnixNativeSerial.cs | 12 +++++++----- dll/serialunix/libnserial/events.c | 6 +++--- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/code/Native/UnixNativeSerial.cs b/code/Native/UnixNativeSerial.cs index 03938259..841a146f 100644 --- a/code/Native/UnixNativeSerial.cs +++ b/code/Native/UnixNativeSerial.cs @@ -795,7 +795,7 @@ private unsafe void ReadWriteThread() byte* bo = b + m_Buffer.Serial.ReadBuffer.End; int length = m_Buffer.Serial.ReadBuffer.WriteLength; rresult = m_Dll.serial_read(m_Handle, (IntPtr)bo, length); - if (rresult == -1) { + if (rresult < 0) { SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Error, 0, "{0}: ReadWriteThread: Error reading data; errno={1}; description={2}", m_Name, m_Dll.errno, m_Dll.serial_error(m_Handle)); @@ -805,7 +805,7 @@ private unsafe void ReadWriteThread() SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: ReadWriteThread: serial_read({1}, {2}, {3}) == {4}", m_Name, m_Handle, (IntPtr)bo, length, rresult); - m_Buffer.Serial.ReadBufferProduce(rresult); + if (rresult > 0) m_Buffer.Serial.ReadBufferProduce(rresult); } } if (rresult > 0) OnDataReceived(this, new SerialDataReceivedEventArgs(SerialData.Chars)); @@ -817,7 +817,7 @@ private unsafe void ReadWriteThread() byte* bo = b + m_Buffer.Serial.WriteBuffer.Start; int length = m_Buffer.Serial.WriteBuffer.ReadLength; wresult = m_Dll.serial_write(m_Handle, (IntPtr)bo, length); - if (wresult == -1) { + if (wresult < 0) { SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Error, 0, "{0}: ReadWriteThread: Error writing data; errno={1}; description={2}", m_Name, m_Dll.errno, m_Dll.serial_error(m_Handle)); @@ -827,8 +827,10 @@ private unsafe void ReadWriteThread() SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0, "{0}: ReadWriteThread: serial_write({1}, {2}, {3}) == {4}", m_Name, m_Handle, (IntPtr)bo, length, wresult); - m_Buffer.Serial.WriteBufferConsume(wresult); - m_Buffer.Serial.TxEmptyEvent(); + if (wresult > 0) { + m_Buffer.Serial.WriteBufferConsume (wresult); + m_Buffer.Serial.TxEmptyEvent (); + } } } } diff --git a/dll/serialunix/libnserial/events.c b/dll/serialunix/libnserial/events.c index edfcfa52..ecf96618 100644 --- a/dll/serialunix/libnserial/events.c +++ b/dll/serialunix/libnserial/events.c @@ -1,6 +1,6 @@ //////////////////////////////////////////////////////////////////////////////// // PROJECT : libnserial -// (C) Jason Curl, 2016. +// (C) Jason Curl, 2016-2017. // // FILE : events.c // @@ -277,7 +277,7 @@ static ssize_t internal_read(struct serialhandle *handle, char *buf, size_t coun errno = EIO; return -1; } else if (readbytes < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { return 0; } serial_seterror(handle, ERRMSG_SERIALREAD); @@ -315,7 +315,7 @@ NSERIAL_EXPORT ssize_t WINAPI serial_write(struct serialhandle *handle, const ch ssize_t writebytes; writebytes = write(handle->fd, buffer, length); if (writebytes < 0) { - if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { return 0; } serial_seterror(handle, ERRMSG_SERIALWRITE);