gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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 "gvisor.dev/gvisor/pkg/abi/linux" 19 "gvisor.dev/gvisor/pkg/log" 20 "gvisor.dev/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 }