mirror of
https://github.com/golang/go
synced 2024-11-08 01:56:14 -07:00
dfb1b69665
Ignored reports whether sig is currently ignored. This implementation only works applies on Unix systems for now. However, at the moment that is also the case for Ignore() and several other signal interaction methods, so that seems fair. Fixes #22497 Change-Id: I7c1b1a5e12373ca5da44709500ff5acedc6f1316 Reviewed-on: https://go-review.googlesource.com/108376 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
160 lines
3.3 KiB
Go
160 lines
3.3 KiB
Go
// Copyright 2009 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// This file implements runtime support for signal handling.
|
|
|
|
package runtime
|
|
|
|
import _ "unsafe"
|
|
|
|
const qsize = 64
|
|
|
|
var sig struct {
|
|
q noteQueue
|
|
inuse bool
|
|
|
|
lock mutex
|
|
note note
|
|
sleeping bool
|
|
}
|
|
|
|
type noteData struct {
|
|
s [_ERRMAX]byte
|
|
n int // n bytes of s are valid
|
|
}
|
|
|
|
type noteQueue struct {
|
|
lock mutex
|
|
data [qsize]noteData
|
|
ri int
|
|
wi int
|
|
full bool
|
|
}
|
|
|
|
// It is not allowed to allocate memory in the signal handler.
|
|
func (q *noteQueue) push(item *byte) bool {
|
|
lock(&q.lock)
|
|
if q.full {
|
|
unlock(&q.lock)
|
|
return false
|
|
}
|
|
s := gostringnocopy(item)
|
|
copy(q.data[q.wi].s[:], s)
|
|
q.data[q.wi].n = len(s)
|
|
q.wi++
|
|
if q.wi == qsize {
|
|
q.wi = 0
|
|
}
|
|
if q.wi == q.ri {
|
|
q.full = true
|
|
}
|
|
unlock(&q.lock)
|
|
return true
|
|
}
|
|
|
|
func (q *noteQueue) pop() string {
|
|
lock(&q.lock)
|
|
q.full = false
|
|
if q.ri == q.wi {
|
|
unlock(&q.lock)
|
|
return ""
|
|
}
|
|
note := &q.data[q.ri]
|
|
item := string(note.s[:note.n])
|
|
q.ri++
|
|
if q.ri == qsize {
|
|
q.ri = 0
|
|
}
|
|
unlock(&q.lock)
|
|
return item
|
|
}
|
|
|
|
// Called from sighandler to send a signal back out of the signal handling thread.
|
|
// Reports whether the signal was sent. If not, the caller typically crashes the program.
|
|
func sendNote(s *byte) bool {
|
|
if !sig.inuse {
|
|
return false
|
|
}
|
|
|
|
// Add signal to outgoing queue.
|
|
if !sig.q.push(s) {
|
|
return false
|
|
}
|
|
|
|
lock(&sig.lock)
|
|
if sig.sleeping {
|
|
sig.sleeping = false
|
|
notewakeup(&sig.note)
|
|
}
|
|
unlock(&sig.lock)
|
|
|
|
return true
|
|
}
|
|
|
|
// Called to receive the next queued signal.
|
|
// Must only be called from a single goroutine at a time.
|
|
//go:linkname signal_recv os/signal.signal_recv
|
|
func signal_recv() string {
|
|
for {
|
|
note := sig.q.pop()
|
|
if note != "" {
|
|
return note
|
|
}
|
|
|
|
lock(&sig.lock)
|
|
sig.sleeping = true
|
|
noteclear(&sig.note)
|
|
unlock(&sig.lock)
|
|
notetsleepg(&sig.note, -1)
|
|
}
|
|
}
|
|
|
|
// signalWaitUntilIdle waits until the signal delivery mechanism is idle.
|
|
// This is used to ensure that we do not drop a signal notification due
|
|
// to a race between disabling a signal and receiving a signal.
|
|
// This assumes that signal delivery has already been disabled for
|
|
// the signal(s) in question, and here we are just waiting to make sure
|
|
// that all the signals have been delivered to the user channels
|
|
// by the os/signal package.
|
|
//go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle
|
|
func signalWaitUntilIdle() {
|
|
for {
|
|
lock(&sig.lock)
|
|
sleeping := sig.sleeping
|
|
unlock(&sig.lock)
|
|
if sleeping {
|
|
return
|
|
}
|
|
Gosched()
|
|
}
|
|
}
|
|
|
|
// Must only be called from a single goroutine at a time.
|
|
//go:linkname signal_enable os/signal.signal_enable
|
|
func signal_enable(s uint32) {
|
|
if !sig.inuse {
|
|
// The first call to signal_enable is for us
|
|
// to use for initialization. It does not pass
|
|
// signal information in m.
|
|
sig.inuse = true // enable reception of signals; cannot disable
|
|
noteclear(&sig.note)
|
|
return
|
|
}
|
|
}
|
|
|
|
// Must only be called from a single goroutine at a time.
|
|
//go:linkname signal_disable os/signal.signal_disable
|
|
func signal_disable(s uint32) {
|
|
}
|
|
|
|
// Must only be called from a single goroutine at a time.
|
|
//go:linkname signal_ignore os/signal.signal_ignore
|
|
func signal_ignore(s uint32) {
|
|
}
|
|
|
|
//go:linkname signal_ignored os/signal.signal_ignored
|
|
func signal_ignored(s uint32) bool {
|
|
return false
|
|
}
|