2019-04-29 21:25:05 +00:00
|
|
|
// Copyright 2018 The gVisor Authors.
|
2018-04-27 17:37:02 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
package kernel
|
|
|
|
|
|
|
|
import (
|
2019-06-13 23:49:09 +00:00
|
|
|
"gvisor.dev/gvisor/pkg/abi/linux"
|
|
|
|
"gvisor.dev/gvisor/pkg/bits"
|
|
|
|
"gvisor.dev/gvisor/pkg/sentry/arch"
|
2018-04-27 17:37:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
// stdSignalCap is the maximum number of instances of a given standard
|
|
|
|
// signal that may be pending. ("[If] multiple instances of a standard
|
|
|
|
// signal are delivered while that signal is currently blocked, then only
|
|
|
|
// one instance is queued.") - signal(7)
|
|
|
|
stdSignalCap = 1
|
|
|
|
|
|
|
|
// rtSignalCap is the maximum number of instances of a given realtime
|
|
|
|
// signal that may be pending.
|
|
|
|
//
|
2019-04-29 21:03:04 +00:00
|
|
|
// TODO(igudger): In Linux, the minimum signal queue size is
|
2018-04-27 17:37:02 +00:00
|
|
|
// RLIMIT_SIGPENDING, which is by default max_threads/2.
|
|
|
|
rtSignalCap = 32
|
|
|
|
)
|
|
|
|
|
|
|
|
// pendingSignals holds a collection of pending signals. The zero value of
|
|
|
|
// pendingSignals is a valid empty collection. pendingSignals is thread-unsafe;
|
|
|
|
// users must provide synchronization.
|
2018-08-02 17:41:44 +00:00
|
|
|
//
|
|
|
|
// +stateify savable
|
2018-04-27 17:37:02 +00:00
|
|
|
type pendingSignals struct {
|
|
|
|
// signals contains all pending signals.
|
|
|
|
//
|
|
|
|
// Note that signals is zero-indexed, but signal 1 is the first valid
|
|
|
|
// signal, so signals[0] contains signals with signo 1 etc. This offset is
|
|
|
|
// usually handled by using Signal.index().
|
2018-08-23 23:31:25 +00:00
|
|
|
signals [linux.SignalMaximum]pendingSignalQueue `state:".([]savedPendingSignal)"`
|
2018-04-27 17:37:02 +00:00
|
|
|
|
|
|
|
// Bit i of pendingSet is set iff there is at least one signal with signo
|
|
|
|
// i+1 pending.
|
2018-06-20 18:01:32 +00:00
|
|
|
pendingSet linux.SignalSet `state:"manual"`
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// pendingSignalQueue holds a pendingSignalList for a single signal number.
|
2018-08-02 17:41:44 +00:00
|
|
|
//
|
|
|
|
// +stateify savable
|
2018-04-27 17:37:02 +00:00
|
|
|
type pendingSignalQueue struct {
|
|
|
|
pendingSignalList
|
|
|
|
length int
|
|
|
|
}
|
|
|
|
|
2018-08-02 17:41:44 +00:00
|
|
|
// +stateify savable
|
2018-04-27 17:37:02 +00:00
|
|
|
type pendingSignal struct {
|
|
|
|
// pendingSignalEntry links into a pendingSignalList.
|
|
|
|
pendingSignalEntry
|
|
|
|
*arch.SignalInfo
|
2018-08-23 23:31:25 +00:00
|
|
|
|
|
|
|
// If timer is not nil, it is the IntervalTimer which sent this signal.
|
|
|
|
timer *IntervalTimer
|
2018-04-27 17:37:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// enqueue enqueues the given signal. enqueue returns true on success and false
|
|
|
|
// on failure (if the given signal's queue is full).
|
|
|
|
//
|
|
|
|
// Preconditions: info represents a valid signal.
|
2018-08-23 23:31:25 +00:00
|
|
|
func (p *pendingSignals) enqueue(info *arch.SignalInfo, timer *IntervalTimer) bool {
|
2018-04-27 17:37:02 +00:00
|
|
|
sig := linux.Signal(info.Signo)
|
|
|
|
q := &p.signals[sig.Index()]
|
|
|
|
if sig.IsStandard() {
|
|
|
|
if q.length >= stdSignalCap {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
} else if q.length >= rtSignalCap {
|
|
|
|
return false
|
|
|
|
}
|
2018-08-23 23:31:25 +00:00
|
|
|
q.pendingSignalList.PushBack(&pendingSignal{SignalInfo: info, timer: timer})
|
2018-04-27 17:37:02 +00:00
|
|
|
q.length++
|
|
|
|
p.pendingSet |= linux.SignalSetOf(sig)
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
// dequeue dequeues and returns any pending signal not masked by mask. If no
|
|
|
|
// unmasked signals are pending, dequeue returns nil.
|
|
|
|
func (p *pendingSignals) dequeue(mask linux.SignalSet) *arch.SignalInfo {
|
|
|
|
// "Real-time signals are delivered in a guaranteed order. Multiple
|
|
|
|
// real-time signals of the same type are delivered in the order they were
|
|
|
|
// sent. If different real-time signals are sent to a process, they are
|
|
|
|
// delivered starting with the lowest-numbered signal. (I.e., low-numbered
|
|
|
|
// signals have highest priority.) By contrast, if multiple standard
|
|
|
|
// signals are pending for a process, the order in which they are delivered
|
|
|
|
// is unspecified. If both standard and real-time signals are pending for a
|
|
|
|
// process, POSIX leaves it unspecified which is delivered first. Linux,
|
|
|
|
// like many other implementations, gives priority to standard signals in
|
|
|
|
// this case." - signal(7)
|
|
|
|
lowestPendingUnblockedBit := bits.TrailingZeros64(uint64(p.pendingSet &^ mask))
|
|
|
|
if lowestPendingUnblockedBit >= linux.SignalMaximum {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
return p.dequeueSpecific(linux.Signal(lowestPendingUnblockedBit + 1))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *pendingSignals) dequeueSpecific(sig linux.Signal) *arch.SignalInfo {
|
|
|
|
q := &p.signals[sig.Index()]
|
|
|
|
ps := q.pendingSignalList.Front()
|
|
|
|
if ps == nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
q.pendingSignalList.Remove(ps)
|
|
|
|
q.length--
|
|
|
|
if q.length == 0 {
|
|
|
|
p.pendingSet &^= linux.SignalSetOf(sig)
|
|
|
|
}
|
2018-08-23 23:31:25 +00:00
|
|
|
if ps.timer != nil {
|
|
|
|
ps.timer.updateDequeuedSignalLocked(ps.SignalInfo)
|
|
|
|
}
|
2018-04-27 17:37:02 +00:00
|
|
|
return ps.SignalInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
// discardSpecific causes all pending signals with number sig to be discarded.
|
|
|
|
func (p *pendingSignals) discardSpecific(sig linux.Signal) {
|
|
|
|
q := &p.signals[sig.Index()]
|
2018-08-23 23:31:25 +00:00
|
|
|
for ps := q.pendingSignalList.Front(); ps != nil; ps = ps.Next() {
|
|
|
|
if ps.timer != nil {
|
|
|
|
ps.timer.signalRejectedLocked()
|
|
|
|
}
|
|
|
|
}
|
2018-04-27 17:37:02 +00:00
|
|
|
q.pendingSignalList.Reset()
|
|
|
|
q.length = 0
|
|
|
|
p.pendingSet &^= linux.SignalSetOf(sig)
|
|
|
|
}
|