unix: Fixed race condition while closing serial port. Added PortClosed error
This commit is contained in:
@@ -100,6 +100,8 @@ const (
|
||||
InvalidStopBits
|
||||
// ErrorEnumeratingPorts an error occurred while listing serial port
|
||||
ErrorEnumeratingPorts
|
||||
// PortClosed the port has been closed while the operation is in progress
|
||||
PortClosed
|
||||
)
|
||||
|
||||
// EncodedErrorString returns a string explaining the error code
|
||||
@@ -123,6 +125,8 @@ func (e PortError) EncodedErrorString() string {
|
||||
return "Port stop bits invalid or not supported"
|
||||
case ErrorEnumeratingPorts:
|
||||
return "Could not enumerate serial ports"
|
||||
case PortClosed:
|
||||
return "Port has been closed"
|
||||
default:
|
||||
return "Other error"
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ type unixPort struct {
|
||||
|
||||
closeLock sync.RWMutex
|
||||
closeSignal *unixutils.Pipe
|
||||
opened bool
|
||||
}
|
||||
|
||||
func (port *unixPort) Close() error {
|
||||
@@ -32,6 +33,7 @@ func (port *unixPort) Close() error {
|
||||
if err := syscall.Close(port.handle); err != nil {
|
||||
return err
|
||||
}
|
||||
port.opened = false
|
||||
|
||||
if port.closeSignal != nil {
|
||||
// Send close signal to all pending reads (if any)
|
||||
@@ -52,12 +54,18 @@ func (port *unixPort) Close() error {
|
||||
func (port *unixPort) Read(p []byte) (n int, err error) {
|
||||
port.closeLock.RLock()
|
||||
defer port.closeLock.RUnlock()
|
||||
if !port.opened {
|
||||
return 0, &PortError{code: PortClosed}
|
||||
}
|
||||
|
||||
fds := unixutils.NewFDSet(port.handle, port.closeSignal.ReadFD())
|
||||
res, err := unixutils.Select(fds, nil, fds, -1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if res.IsReadable(port.closeSignal.ReadFD()) {
|
||||
return 0, &PortError{code: PortClosed}
|
||||
}
|
||||
return syscall.Read(port.handle, p)
|
||||
}
|
||||
|
||||
@@ -98,6 +106,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) {
|
||||
}
|
||||
port := &unixPort{
|
||||
handle: h,
|
||||
opened: true,
|
||||
}
|
||||
|
||||
// Setup serial port
|
||||
@@ -127,7 +136,7 @@ func nativeOpen(portName string, mode *Mode) (*unixPort, error) {
|
||||
|
||||
port.acquireExclusiveAccess()
|
||||
|
||||
// This pipe is used as a signal to cancel blocking Read or Write
|
||||
// This pipe is used as a signal to cancel blocking Read
|
||||
pipe := &unixutils.Pipe{}
|
||||
if err := pipe.Open(); err != nil {
|
||||
port.Close()
|
||||
|
||||
Reference in New Issue
Block a user