dotMorten/NmeaParser

NmeaDevice::CloseAsync does not close serial devices correctly (SerialPortDevice .CloseStreamAsync does not close passed stream )

Closed this issue · 12 comments

mb12 commented

#The current implementation of SerialPortDevice .CloseStreamAsync does not Dispose the passed stream. So if you try to open the device again after calling CloseAsync on it, it would fail.

So applications with the following kind of usage pattern will not work:

OpenDevice
....do something with NMEA data..
CloseDevice

OpenDevice again ============> This will fail because device is not closed correctly.

I've included below relevant code for OpenDevice and CloseDevice at the end.

PS: I tried to Dispose the passed stream in SerialPortDevice .CloseStreamAsync. However it blocks/hangs the application.

void OpenDevice() {
............
...........
	m_device = new NmeaParser.SerialPortDevice(serialDevice);
	m_device.MessageReceived += device_NmeaMessageReceived;
        m_device.OpenAsync();
............
...........
}
void CloseDevice() {
        m_device.CloseAsync();
        m_device = null;
}

Also running into an issue with this as the application isn't closing because the it is still receiving events from the COM Port. I've added code to the closing event of the form, but the Sub I have set up to handle events from the class keeps being called, blocking the closing from happening.

I'm a little confused by this. The method calls Close, and the documentation for close clearly states the stream will be disposed too:

Closes the port connection, sets the System.IO.Ports.SerialPort.IsOpen property to false, and disposes of the internal System.IO.Stream object.

Is this .NET or UWP?

mb12 commented

This is UWP.

Did you dispose the SerialDevice that you parsed in before creating a new one? Or did you reuse the same instance?

Also in your code above, I don't see any awaits on open and close. Are these calls completed before calling the next one?

Is this related to #33?

Mine is .NET, WPF. It is not related to #33. I just called the library as is; I made no changes to. The CloseAsync function says it has run successfully, but the class is still responding to data being received from the COM port, which tells me that the connection to the COM port has not actually closed.

the class is still responding to data being received from the COM port

I don't see how that's possible, as the thread reading the serial port is shut down (the close task won't return until that thread has shut down and I've not been able to reproduce this behavior myself.
I wonder if there's more to it. Any chance you could provide a reproducer sample?

Thank you! I had not noticed the Disposed event on the SerialPort. That's very helpful!

wrt to a reproducer sample, I just meant an app that opens/closes a serial port and causes the crash, and assume I also have a serial port and a device connected to it.

Since the developer creates the serial port and passes it to the NMEA Parser, it's the developer's responsibility to dispose of the serial port, and ensure it's disposed before opening it up again.

All the NMEA Parser is doing is opening and closing the port. It would not be correct if the API would be disposing objects that it is not the creator of.

@mb12 Can you confirm that if you dispose the serial port and wait for the disposed event before opening up the port again, it works? (the sample app should probably be doing this again)

Closing - feel free to open again if you have any extra detail to share or disagree with my previous comment