diff --git a/code/Serial/Windows/CommOverlappedIo.cs b/code/Serial/Windows/CommOverlappedIo.cs index 4efb961..e8676d3 100644 --- a/code/Serial/Windows/CommOverlappedIo.cs +++ b/code/Serial/Windows/CommOverlappedIo.cs @@ -436,20 +436,7 @@ private void OverlappedIoThreadMainLoop() } else if (whandles[ev] == m_ReadEvent) { result = Kernel32.GetOverlappedResult(m_ComPortHandle, ref readOverlapped, out bytes, true); if (!result) { - int win32Error = Marshal.GetLastWin32Error(); - int hr = Marshal.GetHRForLastWin32Error(); - // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered. - if (win32Error != WinError.ERROR_OPERATION_ABORTED || bytes > 0) { - if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error)) - m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error, - $"{m_Name}: SerialThread: Overlapped ReadFile() error {win32Error} bytes {bytes}"); - Marshal.ThrowExceptionForHR(hr); - } else { - // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm - if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) - m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, - $"{m_Name}: SerialThread: Overlapped ReadFile() error {win32Error} bytes {bytes}"); - } + ProcessReadEventError(bytes); } else { ProcessReadEvent(bytes); } @@ -460,20 +447,7 @@ private void OverlappedIoThreadMainLoop() } else if (whandles[ev] == m_WriteEvent) { result = Kernel32.GetOverlappedResult(m_ComPortHandle, ref writeOverlapped, out bytes, true); if (!result) { - int win32Error = Marshal.GetLastWin32Error(); - int hr = Marshal.GetHRForLastWin32Error(); - // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered. - if (win32Error != WinError.ERROR_OPERATION_ABORTED || bytes > 0) { - if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error)) - m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error, - $"{m_Name}: SerialThread: Overlapped WriteFile() error {win32Error} bytes {bytes}"); - Marshal.ThrowExceptionForHR(hr); - } else { - // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm - if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) - m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, - $"{m_Name}: SerialThread: Overlapped WriteFile() error {win32Error} bytes {bytes}"); - } + ProcessWriteEventError(bytes); } else { ProcessWriteEvent(bytes); } @@ -488,20 +462,7 @@ private void OverlappedIoThreadMainLoop() m_PurgePending = true; result = Kernel32.PurgeComm(m_ComPortHandle, Kernel32.PurgeFlags.PURGE_TXABORT | Kernel32.PurgeFlags.PURGE_TXCLEAR); - if (!result) { - int win32Error = Marshal.GetLastWin32Error(); - int hr = Marshal.GetHRForLastWin32Error(); - if (win32Error != WinError.ERROR_OPERATION_ABORTED) { - if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error)) - m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error, - $"{m_Name}: SerialThread: PurgeComm() error {win32Error}"); - Marshal.ThrowExceptionForHR(hr); - } else { - if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) - m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, - $"{m_Name}: SerialThread: PurgeComm() error {win32Error}"); - } - } + if (!result) ProcessPurgeCommError(); } else { if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, $"{m_Name}: SerialThread: Purged"); @@ -698,6 +659,33 @@ private void ProcessReadEvent(uint bytes) } } + private void ProcessReadEventError(uint bytes) + { + int win32Error = Marshal.GetLastWin32Error(); + int hr = Marshal.GetHRForLastWin32Error(); + + // Should never get ERROR_IO_PENDING, as this method is only called when the event is triggered. + if (bytes == 0) { + switch (win32Error) { + case WinError.ERROR_OPERATION_ABORTED: + // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, + "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes); + return; + case WinError.ERROR_HANDLE_EOF: + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Information)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Information, + "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes); + return; + } + } + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error, + "{0}: SerialThread: Overlapped ReadFile() error {1} bytes {2}", m_Name, win32Error, bytes); + Marshal.ThrowExceptionForHR(hr); + } + /// /// Check if we should WriteFile() and update buffers if serial data is immediately cached by driver. /// @@ -779,6 +767,47 @@ private void ProcessWriteEvent(uint bytes) } } + private void ProcessWriteEventError(uint bytes) + { + int win32Error = Marshal.GetLastWin32Error(); + int hr = Marshal.GetHRForLastWin32Error(); + + if (bytes == 0) { + switch (win32Error) { + case WinError.ERROR_OPERATION_ABORTED: + // ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, + "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes); + return; + } + } + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error, + "{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes); + Marshal.ThrowExceptionForHR(hr); + } + + private void ProcessPurgeCommError() + { + int win32Error = Marshal.GetLastWin32Error(); + int hr = Marshal.GetHRForLastWin32Error(); + + switch (win32Error) { + case WinError.ERROR_OPERATION_ABORTED: + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Verbose, + "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error); + return; + default: + if (m_Log.ShouldTrace(System.Diagnostics.TraceEventType.Error)) + m_Log.TraceEvent(System.Diagnostics.TraceEventType.Error, + "{0}: SerialThread: PurgeComm() error {1}", m_Name, win32Error); + Marshal.ThrowExceptionForHR(hr); + break; + } + } + #region Event Handling public event EventHandler CommEvent;