Skip to content

Closing port does not unblock Write #150

@samherrmann

Description

@samherrmann

Consider the following pseudo code for reading from a serial port:

// 1. Open port.
port, _ := serial.Open("/dev/pts/1", mode)

// 2. Listen to the "done" channel that emits when user presses Ctrl+C.
go func() {
  <-done
  port.Close()
}()

// 3. Read from port.
for {
  buff := make([]byte, 1024)
  // If Close is called while Read is blocked (because it's waiting on data) 
  // then Read returns and we can exit the application.
  if _, err = port.Read(buff); err != nil {
    if isPortClosed(err) {
      return nil
    }
    return err
  }
}

In the above example, all works as expected. Calling Close on the port unblocks Read and the application can proceed as desired.

Now consider a similar setup for writing to the serial port:

port, _ := serial.Open("/dev/pts/2", mode)

go func() {
  <-done
  port.Close()
}()

i =: 0
for {
  // If Close is called while Write is blocked 
  // (because no reader exists on the other side) 
  // then Write does *not* return.
  if _, err = port.Write([]byte(fmt.Sprintf("%v", i))); err != nil {
    if isPortClosed(err) {
      return nil
    }
    return err
  }
  i++
  time.Sleep(time.Microsecond)
}

In this example, if Write is blocked because no reader exists on the other side, then calling Close on the port does not force Write to return and the application cannot exit cleanly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions