github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/kernel/tty.go (about)

     1  // Copyright 2018 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package kernel
    16  
    17  import (
    18  	"github.com/MerlinKodo/gvisor/pkg/abi/linux"
    19  	"github.com/MerlinKodo/gvisor/pkg/log"
    20  	"github.com/MerlinKodo/gvisor/pkg/sync"
    21  )
    22  
    23  // TTY defines the relationship between a thread group and its controlling
    24  // terminal.
    25  //
    26  // +stateify savable
    27  type TTY struct {
    28  	// Index is the terminal index. It is immutable.
    29  	Index uint32
    30  
    31  	mu sync.Mutex `state:"nosave"`
    32  
    33  	// tg is protected by mu.
    34  	tg *ThreadGroup
    35  }
    36  
    37  // TTY returns the thread group's controlling terminal. If nil, there is no
    38  // controlling terminal.
    39  func (tg *ThreadGroup) TTY() *TTY {
    40  	tg.pidns.owner.mu.RLock()
    41  	defer tg.pidns.owner.mu.RUnlock()
    42  	tg.signalHandlers.mu.Lock()
    43  	defer tg.signalHandlers.mu.Unlock()
    44  	return tg.tty
    45  }
    46  
    47  // SignalForegroundProcessGroup sends the signal to the foreground process
    48  // group of the TTY.
    49  func (tty *TTY) SignalForegroundProcessGroup(info *linux.SignalInfo) {
    50  	tty.mu.Lock()
    51  	defer tty.mu.Unlock()
    52  
    53  	tg := tty.tg
    54  	if tg == nil {
    55  		// This TTY is not a controlling thread group. This can happen
    56  		// if it was opened with O_NOCTTY, or if it failed the checks
    57  		// on session and leaders in SetControllingTTY(). There is
    58  		// nothing to signal.
    59  		return
    60  	}
    61  
    62  	tg.pidns.owner.mu.Lock()
    63  	tg.signalHandlers.mu.Lock()
    64  	fg := tg.processGroup.session.foreground
    65  	tg.signalHandlers.mu.Unlock()
    66  	tg.pidns.owner.mu.Unlock()
    67  
    68  	if fg == nil {
    69  		// Nothing to signal.
    70  		return
    71  	}
    72  
    73  	// SendSignal will take TaskSet.mu and signalHandlers.mu, so we cannot
    74  	// hold them here.
    75  	if err := fg.SendSignal(info); err != nil {
    76  		log.Warningf("failed to signal foreground process group (pgid=%d): %v", fg.id, err)
    77  	}
    78  }