protected override void Dispose(bool disposing)
        {
            try
            {
                lock (_lock)
                {
                    int handle = Interlocked.Exchange(ref _handle, -1);
                    if (handle >= 0)
                    {
                        NativeMethods.retry(() => NativeMethods.tcsetattr(handle, NativeMethods.TCSANOW, ref _oldSettings));
                        NativeMethods.retry(() => NativeMethods.ioctl(handle, NativeMethods.TIOCNXCL));
                        NativeMethods.retry(() => NativeMethods.close(handle));
                    }
                }
            }
            catch
            {
            }

            base.Dispose(disposing);
        }
        unsafe void UpdateSettings()
        {
            lock (_lock)
            {
                int ret;
                int handle = _handle;
                if (handle >= 0)
                {
                    if (_settingsChanged)
                    {
                        int baudRate = _ser.BaudRate;
                        int dataBits = _ser.DataBits;
                        var parity   = _ser.Parity;
                        int stopBits = _ser.StopBits;

                        ret = NativeMethods.retry(() => NativeMethods.cfsetspeed(ref _newSettings, (UIntPtr)Math.Max(1, baudRate)));
                        if (ret < 0)
                        {
                            throw new IOException("cfsetspeed failed.");
                        }

                        ulong cflag = (ulong)_newSettings.c_cflag;
                        // data bits
                        cflag &= ~NativeMethods.CSIZE;
                        if (dataBits == 7)
                        {
                            cflag |= NativeMethods.CS7;
                        }
                        else
                        {
                            cflag |= NativeMethods.CS8;
                        }
                        // parity bits
                        cflag &= ~NativeMethods.PARENB & ~NativeMethods.PARODD;
                        if (parity == SerialParity.Even)
                        {
                            cflag |= NativeMethods.PARENB;
                        }
                        else if (parity == SerialParity.Odd)
                        {
                            cflag |= NativeMethods.PARENB | NativeMethods.PARODD;
                        }
                        // stop bits
                        cflag &= ~NativeMethods.CSTOPB;
                        if (stopBits == 2)
                        {
                            cflag |= NativeMethods.CSTOPB;
                        }
                        _newSettings.c_cflag = (UIntPtr)cflag;

                        ret = NativeMethods.retry(() => NativeMethods.tcsetattr(handle, NativeMethods.TCSANOW, ref _newSettings));
                        if (ret < 0)
                        {
                            throw new IOException("tcsetattr failed.");
                        }

                        ret = NativeMethods.retry(() => NativeMethods.tcflush(handle, NativeMethods.TCIFLUSH));
                        if (ret < 0)
                        {
                            throw new IOException("tcflush failed.");
                        }

                        _settingsChanged = false;
                    }
                }
            }
        }