jcurl / RJCP.DLL.SerialPortStream

SerialPortStream is an independent implementation of System.IO.Ports.SerialPort and SerialStream for better reliability and maintainability. Default branch is 2.x and now has support for Mono with help of a C library.
Microsoft Public License
624 stars 197 forks source link

Close two serial ports hang on MacOS #67

Closed howlfu closed 5 years ago

howlfu commented 6 years ago

Hi jcurl, Here is my code use dotnet core 2.1:

SerialPortStream tmp1 = new SerialPortStream("/dev/tty.usbserial");
tmp1.Open();  
SerialPortStream tmp2 = new SerialPortStream("/dev/tty.usbserial2");
tmp2.Open();
Thread.Sleep(3000);
tmp1.Close();
tmp2.Close();

And it hangs when tmp2 close. tmp2.Close();

I tried to trace code it stop when call C library,

[DllImport("libnserial.so.1", SetLastError = true)]
        internal static extern int serial_close(SafeSerialHandle handle);

But it goes well on linux, any idea? Thanks.

jcurl commented 6 years ago

Hi, you can in more detail exactly where it hangs if you recompile with logging enabled.

CFLAGS="-O0 -g -Wall" cmake -DCMAKE_BUILD_TYPE=Debug -DNSLOG_ENABLED=ON .. && make

Then the log file will say on exactly which system call it is hanging. Please do that and provide logs. I don't have MacOS to test

howlfu commented 6 years ago

nserial.log

Attachment is the log, 2018.08.28-16:06:43.252476 7 /dev/tty.usbserial16 close: closing serial port

jcurl commented 6 years ago

Thankyou. The problem can occur due to one of two APIs. Can you please send me your config.h file?

The location where it occurs is in this path, either the ioctl or the close.

#if defined HAVE_TERMIOS_EXCLUSIVE
  if (ioctl(handle->fd, TIOCNXCL)) {
    nslog(handle, NSLOG_NOTICE, "close: error setting TIOCNXCL: errno=%d", errno);
  }
#endif

result = close(handle->fd);

Also, does the problem only occur with /dev/tty.usbserial16? If you were to swap the ports would it work? I've seen some bluetooth adapters do strange things.

Can you also provide for reference the serial hardware you're using?

howlfu commented 6 years ago

Thanks for your prompt reply. Here is config.h. config.h.zip

This problem occur when you close second port, no matter /dev/tty.usbserial16 or /dev/tty.usbserial. Swap the ports still hang. But when only plug one port to MacOS, it works normally.

The reference hardware:

  1. LoRa module to USB. https://www.microchip.com/wwwproducts/en/RN2903
  2. NBIoT usb device
jcurl commented 6 years ago

OK. The MacOS-X says it supports TIONCXL. If you were to modify the config.h to remove the defines and recompile, does it work?

Remove these lines please from config.h and execute make again. This will tell me if the drivers in MacOS

#define HAVE_TERMIOS_TIOCNXCL
#define HAVE_TERMIOS_TIOCEXCL
#if defined(HAVE_TERMIOS_TIOCEXCL) && defined(HAVE_TERMIOS_TIOCNXCL)
#define HAVE_TERMIOS_EXCLUSIVE
#endif

This tells the system that opening and closing the drivers should have exclusive access (i.e. while open, a second open should fail).

If it works, either you are opening the same serial port twice, once in .NET, another somewhere in a different application, or MacOS is buggy and doesn't behave as expected.

jcurl commented 5 years ago

Hi, do you have feedback if removing TIOCNXL works?

jcurl commented 5 years ago

As I have no MAC to test, could you please confirm if TIOCNXL is the problem?