[pty] Return enqueued data and then EIO if the replica is closed

PiperOrigin-RevId: 532496868
This commit is contained in:
gVisor bot
2023-05-16 10:15:01 -07:00
parent 595d424651
commit 243aeddd59
4 changed files with 47 additions and 1 deletions
@@ -106,6 +106,9 @@ type lineDiscipline struct {
// handling certain special characters like backspace.
column int
// numReplicas is the number of replica file descriptors.
numReplicas int
// masterWaiter is used to wait on the master end of the TTY.
masterWaiter waiter.Queue
@@ -269,6 +272,20 @@ func (l *lineDiscipline) outputQueueWrite(ctx context.Context, src usermem.IOSeq
return 0, linuxerr.ErrWouldBlock
}
// replicaOpen is called when a replica file descriptor is opened.
func (l *lineDiscipline) replicaOpen() {
l.termiosMu.Lock()
defer l.termiosMu.Unlock()
l.numReplicas++
}
// replicaClose is called when a replica file descriptor is closed.
func (l *lineDiscipline) replicaClose() {
l.termiosMu.Lock()
defer l.termiosMu.Unlock()
l.numReplicas--
}
// transformer is a helper interface to make it easier to stateify queue.
type transformer interface {
// transform functions require queue's mutex to be held.
+3
View File
@@ -110,6 +110,9 @@ func (q *queue) read(ctx context.Context, dst usermem.IOSequence, l *lineDiscipl
defer q.mu.Unlock()
if !q.readable {
if l.numReplicas == 0 {
return 0, false, false, linuxerr.EIO
}
return 0, false, false, linuxerr.ErrWouldBlock
}
+4 -1
View File
@@ -69,6 +69,7 @@ func (ri *replicaInode) Open(ctx context.Context, rp *vfs.ResolvingPath, d *kern
// ignored silently.
_ = t.ThreadGroup().SetControllingTTY(fd.inode.t.replicaKTTY, false /* steal */, fd.vfsfd.IsReadable())
}
ri.t.ld.replicaOpen()
return &fd.vfsfd, nil
}
@@ -114,7 +115,9 @@ type replicaFileDescription struct {
var _ vfs.FileDescriptionImpl = (*replicaFileDescription)(nil)
// Release implements fs.FileOperations.Release.
func (rfd *replicaFileDescription) Release(ctx context.Context) {}
func (rfd *replicaFileDescription) Release(ctx context.Context) {
rfd.inode.t.ld.replicaClose()
}
// EventRegister implements waiter.Waitable.EventRegister.
func (rfd *replicaFileDescription) EventRegister(e *waiter.Entry) error {