1
0
mirror of https://github.com/golang/go synced 2024-11-08 01:56:14 -07:00
go/src/runtime/sigqueue_plan9.go
Adam Azarchs dfb1b69665 os/signal: add func Ignored(sig Signal) bool
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>
2018-04-21 04:18:03 +00:00

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
}