1// Copyright 2009 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// This file implements runtime support for signal handling. 6 7package runtime 8 9import _ "unsafe" 10 11const qsize = 64 12 13var sig struct { 14 q noteQueue 15 inuse bool 16 17 lock mutex 18 note note 19 sleeping bool 20} 21 22type noteData struct { 23 s [_ERRMAX]byte 24 n int // n bytes of s are valid 25} 26 27type noteQueue struct { 28 lock mutex 29 data [qsize]noteData 30 ri int 31 wi int 32 full bool 33} 34 35// It is not allowed to allocate memory in the signal handler. 36func (q *noteQueue) push(item *byte) bool { 37 lock(&q.lock) 38 if q.full { 39 unlock(&q.lock) 40 return false 41 } 42 s := gostringnocopy(item) 43 copy(q.data[q.wi].s[:], s) 44 q.data[q.wi].n = len(s) 45 q.wi++ 46 if q.wi == qsize { 47 q.wi = 0 48 } 49 if q.wi == q.ri { 50 q.full = true 51 } 52 unlock(&q.lock) 53 return true 54} 55 56func (q *noteQueue) pop() string { 57 lock(&q.lock) 58 q.full = false 59 if q.ri == q.wi { 60 unlock(&q.lock) 61 return "" 62 } 63 note := &q.data[q.ri] 64 item := string(note.s[:note.n]) 65 q.ri++ 66 if q.ri == qsize { 67 q.ri = 0 68 } 69 unlock(&q.lock) 70 return item 71} 72 73// Called from sighandler to send a signal back out of the signal handling thread. 74// Reports whether the signal was sent. If not, the caller typically crashes the program. 75func sendNote(s *byte) bool { 76 if !sig.inuse { 77 return false 78 } 79 80 // Add signal to outgoing queue. 81 if !sig.q.push(s) { 82 return false 83 } 84 85 lock(&sig.lock) 86 if sig.sleeping { 87 sig.sleeping = false 88 notewakeup(&sig.note) 89 } 90 unlock(&sig.lock) 91 92 return true 93} 94 95// Called to receive the next queued signal. 96// Must only be called from a single goroutine at a time. 97// 98//go:linkname signal_recv os/signal.signal_recv 99func signal_recv() string { 100 for { 101 note := sig.q.pop() 102 if note != "" { 103 return note 104 } 105 106 lock(&sig.lock) 107 sig.sleeping = true 108 noteclear(&sig.note) 109 unlock(&sig.lock) 110 notetsleepg(&sig.note, -1) 111 } 112} 113 114// signalWaitUntilIdle waits until the signal delivery mechanism is idle. 115// This is used to ensure that we do not drop a signal notification due 116// to a race between disabling a signal and receiving a signal. 117// This assumes that signal delivery has already been disabled for 118// the signal(s) in question, and here we are just waiting to make sure 119// that all the signals have been delivered to the user channels 120// by the os/signal package. 121// 122//go:linkname signalWaitUntilIdle os/signal.signalWaitUntilIdle 123func signalWaitUntilIdle() { 124 for { 125 lock(&sig.lock) 126 sleeping := sig.sleeping 127 unlock(&sig.lock) 128 if sleeping { 129 return 130 } 131 Gosched() 132 } 133} 134 135// Must only be called from a single goroutine at a time. 136// 137//go:linkname signal_enable os/signal.signal_enable 138func signal_enable(s uint32) { 139 if !sig.inuse { 140 // This is the first call to signal_enable. Initialize. 141 sig.inuse = true // enable reception of signals; cannot disable 142 noteclear(&sig.note) 143 } 144} 145 146// Must only be called from a single goroutine at a time. 147// 148//go:linkname signal_disable os/signal.signal_disable 149func signal_disable(s uint32) { 150} 151 152// Must only be called from a single goroutine at a time. 153// 154//go:linkname signal_ignore os/signal.signal_ignore 155func signal_ignore(s uint32) { 156} 157 158//go:linkname signal_ignored os/signal.signal_ignored 159func signal_ignored(s uint32) bool { 160 return false 161} 162