mattn / go-tty

MIT License
208 stars 18 forks source link

Device not closed after close tty #50

Closed fess932 closed 2 months ago

fess932 commented 2 months ago
var err error
stty, err = gotty.OpenDevice(ptyPath)
if err != nil {
    log.Printf("failed to open stty: %v", err)
    return
}
defer func() {
    if gerr := stty.Close(); gerr != nil {
        log.Err(gerr).Msgf("failed to close stty")
    }
}()

result

root@n2-az1:~# fuser /dev/pts/1 -v
                     USER        PID ACCESS COMMAND
/dev/pts/1:          root       1086 F.... vmagent
mattn commented 2 months ago

could you provide whole source code ?

mattn commented 2 months ago

addressed in https://github.com/mattn/go-tty/pull/51

fess932 commented 2 months ago

almost helped, maybe it's worth calling this function

if err = syscall.SetNonblock(int(tty.in.Fd()), true); err != nil {
return nil, err
}

otherwise I get stuck with no returning error on the ReadRune() function in another goroutine, I found something similar here https://stackoverflow.com/questions/74886459/golang-why-does-setdeadline-setreaddeadline-setwritedeadline-not-work-on-a-file

my code

var stty *gotty.TTY
{
  var err error
  stty, err = gotty.OpenDevice(ptyPath)
  if err != nil {
    log.Printf("failed to open stty: %v", err)
    return
  }

  defer func() {
    if derr := stty.Close(); derr != nil {
    log.Err(derr).Msgf("failed to close stty")
  }
  log.Debug().Msgf("stty closed")
}()

backup, err := stty.Raw()
if err != nil {
  log.Printf("failed to open raw stty: %v", err)
  return
}

defer func() {
  if derr := backup(); derr != nil {
    log.Printf("failed to return raw tty backup: %v", derr)
  }
}()

go func() {
  for {
    rn, err := stty.ReadRune() // todo not return error on stty.Close()
    if err != nil {
      log.Err(err).Msgf("failed to read rune")
      return
    }
    fmt.Println(string(rn))
  }
}()

if _, err := stty.Output().Write([]byte("example"); err != nil {
  log.Printf("failed to write to raw stty: %v", err.Error())
  return
}

i add

func (tty *TTY) raw() (func() error, error) {
  ...
  if err = unix.IoctlSetTermios(int(tty.in.Fd()), ioctlWriteTermios, termios); err != nil {
    return nil, err
  }
  if err = syscall.SetNonblock(int(tty.in.Fd()), true); err != nil {
  return nil, err
  }
  ...

and all works, ReadRune returning right error and gorutine stops

fess932 commented 2 months ago

fix read after tty close #52