Closed me-axentia closed 7 years ago
The error 121 is important here. I need to follow up with windows docs on what this means. Do you have details about the driver of the serial port you are using?
Can you write a single NUnit test case that I can also test on my machines, win7 and win10 with the various serial devices I have?
Otherwise thanks for the report! It's well written.
Windows msdn has:
ERROR_SEM_TIMEOUT 121 (0x79) The semaphore timeout period has expired
My first estimate would be to ignore this error and try again. Can you build yourself, or do you need a binary for testing? If you can build yourself, I would look into what line you should change (should be obvious from the log).
I also want to mention, such an error can only come from the serial driver you have. Could you also consider updating, or using a different version of the driver?
Thank you for fast reply! I am using Windows driver usbser.sys 10.0.14393.0 (rs1_release.160715-1616). However, I should mention that the USB device is custom made (developed by me), but the devices does not appear to crash (and sending the data with TeraTerm works).
I used Nuget to include the dll. I have cloned and successfully built the 4.5 solution. But I'm not sure how to use the self-built dll in my project... I have to look into that (I'm not that used to high level programming).
How do I make a NUnit test case that you can test?
I'll make some tests tomorrow afternoon and let you know what you can do
Skipping the error did not seem to help. Data is flowing good but then suddenly data is piled up. There appears to be a problem with emptying a buffer, either in the driver or in the USB device. I'm starting to guess the problem is in the USB device (in that case I'm sorry I bothered you) but I will try to find out more exactly what happens. This is a log that shows that data is piling up (there are a lot of 44 and 88 byte entries preceding this that I cropped away):
IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64191957, 88, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 88 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192045, 44, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 44 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192089, 88, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 88 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192177, 44, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 44 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192221, 132, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 132 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192353, 176, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 176 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192529, 132, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 132 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192661, 220, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 220 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64192881, 264, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 264 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64193145, 396, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 396 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64193541, 528, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 528 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64194069, 616, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 616 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64194685, 704, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 704 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64195389, 924, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 924 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64196313, 1100, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWriteEvent: 1100 bytes IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: DoWriteEvent: WriteFile(1904, 64197413, 1496, ...) == False IO.Ports.SerialPortStream Verbose: 0 : COM12: SerialThread: ProcessWaitCommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Verbose: 0 : COM12: CommEvent: EV_TXEMPTY IO.Ports.SerialPortStream Error: 0 : COM12: SerialThread: Overlapped WriteFile() error 121 bytes 0
I've done a few things to investigate this. I've written a small test case that simulates what you said writing to a COM port:
[Test]
public void WriteLineContinuously()
{
using (SerialPortStream serial = new SerialPortStream(c_SourcePort, 115200, 8, Parity.None, StopBits.One)) {
serial.Open();
for (int i = 0; i < 100000; i++) {
if (i % 100 == 0) Console.WriteLine("WriteLine: {0}", i);
serial.WriteLine("1234567890123456789012345678901234567890123");
}
Thread.Sleep(10000);
}
}
It runs to completion, it writes the 100,000 lines and the entire time shows no error with a PL2303 using Windows 10 (1703 Creators Update).
I've tried investigating on the Web about usbser.sys and what could cause ERROR_SEM_TIMEOUT. There is no public source code for this driver, nor any documentation, except other people suspect their driver is buggy. This site: http://janaxelson.com/serport.htm#usb_virtual_com_ports
has some interesting information, but other drivers appear to be available only on purchase. No idea how much.
The only thing I can think of is that there is a problem in the USB link between your chip implementing the CDC protocol and windows, so the windows driver gets into a problem. A USB analyser might help you there (I remember that WireShark now appears to have the ability to log USB, but I've never used it). Ensure that your wires are well shielded and as short as possible.
I assume that when you write you ignore the error (can't tell what you did from the logs), you modified the file CommOverlappedIo.cs
in the method here (the commented out line Marshal.ThrowExceptionForHR(hr)).
} else if (whandles[ev] == m_WriteEvent) {
result = UnsafeNativeMethods.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) {
SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Error, 0,
"{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
// Marshal.ThrowExceptionForHR(hr);
} else {
// ERROR_OPERATION_ABORTED may be caused by CancelIo or PurgeComm
if (SerialTrace.TraceSer.Switch.ShouldTrace(System.Diagnostics.TraceEventType.Verbose)) {
SerialTrace.TraceSer.TraceEvent(System.Diagnostics.TraceEventType.Verbose, 0,
"{0}: SerialThread: Overlapped WriteFile() error {1} bytes {2}", m_Name, win32Error, bytes);
}
}
} else {
ProcessWriteEvent(bytes);
}
writePending = false;
I can't say why it blocks if you did comment out that line. writePending
would be set back to false
and at the beginning of the I/O loop it will call DoWriteEvent
again that causes a new write so we should see again DoWriteEvent: WriteFile(handle, bufPtr, bufLen, ...) == result
. You could try manually resetting the semaphore m_WriteEvent.Reset()
.
But again, I suspect now the driver has gone into a two minute timeout (a common value reading internet forums).
As I've not heard anything and it appears that there are no workarounds, I'm closing this issue. I don't think there's anything I can do. If you get more information on this topic, please open a new ticket, or have this one reopened.
Hi First of all, thank you very much for this library! It is very useful and much appreciated. However, I have bumped into a problem where the I/O thread is closing down after a while when a try to send a large amount of text data (~160kB). The data is sent by calling WriteLine with approximately 3600 lines of 44 characters. But after 1000-2000 lines (not same every time) I get the exception:
I have managed to enable trace:
This problem is verified on two different Windows 10 computers using SerialPortStream 2.1.1.0. I can send the file without problems using TeraTerm.
Du you have any thoughts about what could be the problem?