]>
Commit | Line | Data |
---|---|---|
87211034 | 1 | // Copyright 2012 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 | ||
03118c21 | 5 | // +build aix darwin dragonfly freebsd linux netbsd openbsd solaris |
87211034 | 6 | |
7 | package runtime | |
8 | ||
ccea2b36 | 9 | import ( |
e104cab8 | 10 | "runtime/internal/atomic" |
ccea2b36 | 11 | "unsafe" |
12 | ) | |
13 | ||
14 | // For gccgo's C code to call: | |
15 | //go:linkname initsig runtime.initsig | |
ccea2b36 | 16 | //go:linkname sigtrampgo runtime.sigtrampgo |
87211034 | 17 | |
33d1d391 | 18 | // sigTabT is the type of an entry in the global sigtable array. |
19 | // sigtable is inherently system dependent, and appears in OS-specific files, | |
20 | // but sigTabT is the same for all Unixy systems. | |
21 | // The sigtable array is indexed by a system signal number to get the flags | |
22 | // and printable name of each signal. | |
23 | type sigTabT struct { | |
24 | flags int32 | |
25 | name string | |
26 | } | |
27 | ||
87211034 | 28 | //go:linkname os_sigpipe os.sigpipe |
29 | func os_sigpipe() { | |
30 | systemstack(sigpipe) | |
31 | } | |
32 | ||
33 | func signame(sig uint32) string { | |
34 | if sig >= uint32(len(sigtable)) { | |
35 | return "" | |
36 | } | |
37 | return sigtable[sig].name | |
38 | } | |
ccea2b36 | 39 | |
40 | const ( | |
41 | _SIG_DFL uintptr = 0 | |
42 | _SIG_IGN uintptr = 1 | |
43 | ) | |
44 | ||
45 | // Stores the signal handlers registered before Go installed its own. | |
46 | // These signal handlers will be invoked in cases where Go doesn't want to | |
47 | // handle a particular signal (e.g., signal occurred on a non-Go thread). | |
e104cab8 | 48 | // See sigfwdgo for more information on when the signals are forwarded. |
ccea2b36 | 49 | // |
e104cab8 | 50 | // This is read by the signal handler; accesses should use |
51 | // atomic.Loaduintptr and atomic.Storeuintptr. | |
ccea2b36 | 52 | var fwdSig [_NSIG]uintptr |
53 | ||
e104cab8 | 54 | // handlingSig is indexed by signal number and is non-zero if we are |
55 | // currently handling the signal. Or, to put it another way, whether | |
56 | // the signal handler is currently set to the Go signal handler or not. | |
57 | // This is uint32 rather than bool so that we can use atomic instructions. | |
58 | var handlingSig [_NSIG]uint32 | |
59 | ||
ccea2b36 | 60 | // channels for synchronizing signal mask updates with the signal mask |
61 | // thread | |
62 | var ( | |
63 | disableSigChan chan uint32 | |
64 | enableSigChan chan uint32 | |
65 | maskUpdatedChan chan struct{} | |
66 | ) | |
67 | ||
68 | func init() { | |
69 | // _NSIG is the number of signals on this operating system. | |
70 | // sigtable should describe what to do for all the possible signals. | |
71 | if len(sigtable) != _NSIG { | |
72 | print("runtime: len(sigtable)=", len(sigtable), " _NSIG=", _NSIG, "\n") | |
73 | throw("bad sigtable len") | |
74 | } | |
75 | } | |
76 | ||
77 | var signalsOK bool | |
78 | ||
79 | // Initialize signals. | |
80 | // Called by libpreinit so runtime may not be initialized. | |
81 | //go:nosplit | |
82 | //go:nowritebarrierrec | |
83 | func initsig(preinit bool) { | |
0f4225ca | 84 | if preinit { |
85 | // preinit is only passed as true if isarchive should be true. | |
86 | isarchive = true | |
87 | } | |
88 | ||
ccea2b36 | 89 | if !preinit { |
90 | // It's now OK for signal handlers to run. | |
91 | signalsOK = true | |
92 | } | |
93 | ||
94 | // For c-archive/c-shared this is called by libpreinit with | |
95 | // preinit == true. | |
96 | if (isarchive || islibrary) && !preinit { | |
97 | return | |
98 | } | |
99 | ||
100 | for i := uint32(0); i < _NSIG; i++ { | |
101 | t := &sigtable[i] | |
102 | if t.flags == 0 || t.flags&_SigDefault != 0 { | |
103 | continue | |
104 | } | |
e104cab8 | 105 | |
106 | // We don't need to use atomic operations here because | |
107 | // there shouldn't be any other goroutines running yet. | |
ccea2b36 | 108 | fwdSig[i] = getsig(i) |
109 | ||
110 | if !sigInstallGoHandler(i) { | |
111 | // Even if we are not installing a signal handler, | |
112 | // set SA_ONSTACK if necessary. | |
113 | if fwdSig[i] != _SIG_DFL && fwdSig[i] != _SIG_IGN { | |
114 | setsigstack(i) | |
b0751b12 | 115 | } else if fwdSig[i] == _SIG_IGN { |
116 | sigInitIgnored(i) | |
ccea2b36 | 117 | } |
118 | continue | |
119 | } | |
120 | ||
e104cab8 | 121 | handlingSig[i] = 1 |
ccea2b36 | 122 | setsig(i, getSigtramp()) |
123 | } | |
124 | } | |
125 | ||
126 | //go:nosplit | |
127 | //go:nowritebarrierrec | |
128 | func sigInstallGoHandler(sig uint32) bool { | |
129 | // For some signals, we respect an inherited SIG_IGN handler | |
130 | // rather than insist on installing our own default handler. | |
131 | // Even these signals can be fetched using the os/signal package. | |
132 | switch sig { | |
133 | case _SIGHUP, _SIGINT: | |
e104cab8 | 134 | if atomic.Loaduintptr(&fwdSig[sig]) == _SIG_IGN { |
ccea2b36 | 135 | return false |
136 | } | |
137 | } | |
138 | ||
139 | t := &sigtable[sig] | |
140 | if t.flags&_SigSetStack != 0 { | |
141 | return false | |
142 | } | |
143 | ||
144 | // When built using c-archive or c-shared, only install signal | |
80a09156 | 145 | // handlers for synchronous signals, SIGPIPE, and SIGURG. |
146 | if (isarchive || islibrary) && t.flags&_SigPanic == 0 && sig != _SIGPIPE && sig != _SIGURG { | |
ccea2b36 | 147 | return false |
148 | } | |
149 | ||
150 | return true | |
151 | } | |
152 | ||
e104cab8 | 153 | // sigenable enables the Go signal handler to catch the signal sig. |
154 | // It is only called while holding the os/signal.handlers lock, | |
155 | // via os/signal.enableSignal and signal_enable. | |
ccea2b36 | 156 | func sigenable(sig uint32) { |
157 | if sig >= uint32(len(sigtable)) { | |
158 | return | |
159 | } | |
160 | ||
e104cab8 | 161 | // SIGPROF is handled specially for profiling. |
162 | if sig == _SIGPROF { | |
163 | return | |
164 | } | |
165 | ||
ccea2b36 | 166 | t := &sigtable[sig] |
167 | if t.flags&_SigNotify != 0 { | |
168 | ensureSigM() | |
169 | enableSigChan <- sig | |
170 | <-maskUpdatedChan | |
e104cab8 | 171 | if atomic.Cas(&handlingSig[sig], 0, 1) { |
172 | atomic.Storeuintptr(&fwdSig[sig], getsig(sig)) | |
ccea2b36 | 173 | setsig(sig, getSigtramp()) |
174 | } | |
175 | } | |
176 | } | |
177 | ||
e104cab8 | 178 | // sigdisable disables the Go signal handler for the signal sig. |
179 | // It is only called while holding the os/signal.handlers lock, | |
180 | // via os/signal.disableSignal and signal_disable. | |
ccea2b36 | 181 | func sigdisable(sig uint32) { |
182 | if sig >= uint32(len(sigtable)) { | |
183 | return | |
184 | } | |
185 | ||
e104cab8 | 186 | // SIGPROF is handled specially for profiling. |
187 | if sig == _SIGPROF { | |
188 | return | |
189 | } | |
190 | ||
ccea2b36 | 191 | t := &sigtable[sig] |
192 | if t.flags&_SigNotify != 0 { | |
193 | ensureSigM() | |
194 | disableSigChan <- sig | |
195 | <-maskUpdatedChan | |
196 | ||
197 | // If initsig does not install a signal handler for a | |
198 | // signal, then to go back to the state before Notify | |
199 | // we should remove the one we installed. | |
200 | if !sigInstallGoHandler(sig) { | |
e104cab8 | 201 | atomic.Store(&handlingSig[sig], 0) |
202 | setsig(sig, atomic.Loaduintptr(&fwdSig[sig])) | |
ccea2b36 | 203 | } |
204 | } | |
205 | } | |
206 | ||
e104cab8 | 207 | // sigignore ignores the signal sig. |
208 | // It is only called while holding the os/signal.handlers lock, | |
209 | // via os/signal.ignoreSignal and signal_ignore. | |
ccea2b36 | 210 | func sigignore(sig uint32) { |
211 | if sig >= uint32(len(sigtable)) { | |
212 | return | |
213 | } | |
214 | ||
e104cab8 | 215 | // SIGPROF is handled specially for profiling. |
216 | if sig == _SIGPROF { | |
217 | return | |
218 | } | |
219 | ||
ccea2b36 | 220 | t := &sigtable[sig] |
221 | if t.flags&_SigNotify != 0 { | |
e104cab8 | 222 | atomic.Store(&handlingSig[sig], 0) |
ccea2b36 | 223 | setsig(sig, _SIG_IGN) |
224 | } | |
225 | } | |
226 | ||
e104cab8 | 227 | // clearSignalHandlers clears all signal handlers that are not ignored |
228 | // back to the default. This is called by the child after a fork, so that | |
229 | // we can enable the signal mask for the exec without worrying about | |
230 | // running a signal handler in the child. | |
231 | //go:nosplit | |
232 | //go:nowritebarrierrec | |
233 | func clearSignalHandlers() { | |
234 | for i := uint32(0); i < _NSIG; i++ { | |
235 | if atomic.Load(&handlingSig[i]) != 0 { | |
236 | setsig(i, _SIG_DFL) | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | // setProcessCPUProfiler is called when the profiling timer changes. | |
242 | // It is called with prof.lock held. hz is the new timer, and is 0 if | |
243 | // profiling is being disabled. Enable or disable the signal as | |
244 | // required for -buildmode=c-archive. | |
245 | func setProcessCPUProfiler(hz int32) { | |
246 | if hz != 0 { | |
247 | // Enable the Go signal handler if not enabled. | |
248 | if atomic.Cas(&handlingSig[_SIGPROF], 0, 1) { | |
249 | atomic.Storeuintptr(&fwdSig[_SIGPROF], getsig(_SIGPROF)) | |
f88ce9d1 | 250 | setsig(_SIGPROF, getSigtramp()) |
e104cab8 | 251 | } |
252 | } else { | |
253 | // If the Go signal handler should be disabled by default, | |
254 | // disable it if it is enabled. | |
255 | if !sigInstallGoHandler(_SIGPROF) { | |
256 | if atomic.Cas(&handlingSig[_SIGPROF], 1, 0) { | |
257 | setsig(_SIGPROF, atomic.Loaduintptr(&fwdSig[_SIGPROF])) | |
258 | } | |
259 | } | |
260 | } | |
261 | } | |
262 | ||
263 | // setThreadCPUProfiler makes any thread-specific changes required to | |
264 | // implement profiling at a rate of hz. | |
265 | func setThreadCPUProfiler(hz int32) { | |
ccea2b36 | 266 | var it _itimerval |
267 | if hz == 0 { | |
268 | setitimer(_ITIMER_PROF, &it, nil) | |
269 | } else { | |
270 | it.it_interval.tv_sec = 0 | |
271 | it.it_interval.set_usec(1000000 / hz) | |
272 | it.it_value = it.it_interval | |
273 | setitimer(_ITIMER_PROF, &it, nil) | |
274 | } | |
275 | _g_ := getg() | |
276 | _g_.m.profilehz = hz | |
277 | } | |
278 | ||
279 | func sigpipe() { | |
280 | if sigsend(_SIGPIPE) { | |
281 | return | |
282 | } | |
283 | dieFromSignal(_SIGPIPE) | |
284 | } | |
285 | ||
286 | // sigtrampgo is called from the signal handler function, sigtramp, | |
287 | // written in assembly code. | |
288 | // This is called by the signal handler, and the world may be stopped. | |
33d1d391 | 289 | // |
290 | // It must be nosplit because getg() is still the G that was running | |
291 | // (if any) when the signal was delivered, but it's (usually) called | |
292 | // on the gsignal stack. Until this switches the G to gsignal, the | |
293 | // stack bounds check won't work. | |
294 | // | |
ccea2b36 | 295 | //go:nosplit |
296 | //go:nowritebarrierrec | |
ae306c0a | 297 | func sigtrampgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) { |
ccea2b36 | 298 | if sigfwdgo(sig, info, ctx) { |
299 | return | |
300 | } | |
301 | g := getg() | |
302 | if g == nil { | |
303 | c := sigctxt{info, ctx} | |
304 | if sig == _SIGPROF { | |
305 | _, pc := getSiginfo(info, ctx) | |
03118c21 | 306 | sigprofNonGo(pc) |
ccea2b36 | 307 | return |
308 | } | |
309 | badsignal(uintptr(sig), &c) | |
310 | return | |
311 | } | |
312 | ||
313 | setg(g.m.gsignal) | |
314 | sighandler(sig, info, ctx, g) | |
315 | setg(g) | |
316 | } | |
317 | ||
318 | // sigpanic turns a synchronous signal into a run-time panic. | |
319 | // If the signal handler sees a synchronous panic, it arranges the | |
320 | // stack to look like the function where the signal occurred called | |
321 | // sigpanic, sets the signal's PC value to sigpanic, and returns from | |
322 | // the signal handler. The effect is that the program will act as | |
323 | // though the function that got the signal simply called sigpanic | |
324 | // instead. | |
6a92dd41 | 325 | // |
326 | // This must NOT be nosplit because the linker doesn't know where | |
327 | // sigpanic calls can be injected. | |
328 | // | |
329 | // The signal handler must not inject a call to sigpanic if | |
330 | // getg().throwsplit, since sigpanic may need to grow the stack. | |
ccea2b36 | 331 | func sigpanic() { |
332 | g := getg() | |
333 | if !canpanic(g) { | |
334 | throw("unexpected signal during runtime execution") | |
335 | } | |
336 | ||
337 | switch g.sig { | |
338 | case _SIGBUS: | |
339 | if g.sigcode0 == _BUS_ADRERR && g.sigcode1 < 0x1000 { | |
340 | panicmem() | |
341 | } | |
342 | // Support runtime/debug.SetPanicOnFault. | |
343 | if g.paniconfault { | |
344 | panicmem() | |
345 | } | |
346 | print("unexpected fault address ", hex(g.sigcode1), "\n") | |
347 | throw("fault") | |
348 | case _SIGSEGV: | |
349 | if (g.sigcode0 == 0 || g.sigcode0 == _SEGV_MAPERR || g.sigcode0 == _SEGV_ACCERR) && g.sigcode1 < 0x1000 { | |
350 | panicmem() | |
351 | } | |
352 | // Support runtime/debug.SetPanicOnFault. | |
353 | if g.paniconfault { | |
354 | panicmem() | |
355 | } | |
356 | print("unexpected fault address ", hex(g.sigcode1), "\n") | |
357 | throw("fault") | |
358 | case _SIGFPE: | |
359 | switch g.sigcode0 { | |
360 | case _FPE_INTDIV: | |
361 | panicdivide() | |
362 | case _FPE_INTOVF: | |
363 | panicoverflow() | |
364 | } | |
365 | panicfloat() | |
366 | } | |
367 | ||
368 | if g.sig >= uint32(len(sigtable)) { | |
369 | // can't happen: we looked up g.sig in sigtable to decide to call sigpanic | |
370 | throw("unexpected signal value") | |
371 | } | |
372 | panic(errorString(sigtable[g.sig].name)) | |
373 | } | |
374 | ||
375 | // dieFromSignal kills the program with a signal. | |
376 | // This provides the expected exit status for the shell. | |
377 | // This is only called with fatal signals expected to kill the process. | |
378 | //go:nosplit | |
379 | //go:nowritebarrierrec | |
380 | func dieFromSignal(sig uint32) { | |
ccea2b36 | 381 | unblocksig(sig) |
33d1d391 | 382 | // Mark the signal as unhandled to ensure it is forwarded. |
383 | atomic.Store(&handlingSig[sig], 0) | |
ccea2b36 | 384 | raise(sig) |
385 | ||
386 | // That should have killed us. On some systems, though, raise | |
387 | // sends the signal to the whole process rather than to just | |
388 | // the current thread, which means that the signal may not yet | |
389 | // have been delivered. Give other threads a chance to run and | |
390 | // pick up the signal. | |
391 | osyield() | |
392 | osyield() | |
393 | osyield() | |
394 | ||
33d1d391 | 395 | // If that didn't work, try _SIG_DFL. |
396 | setsig(sig, _SIG_DFL) | |
397 | raise(sig) | |
398 | ||
399 | osyield() | |
400 | osyield() | |
401 | osyield() | |
402 | ||
ccea2b36 | 403 | // If we are still somehow running, just exit with the wrong status. |
404 | exit(2) | |
405 | } | |
406 | ||
407 | // raisebadsignal is called when a signal is received on a non-Go | |
408 | // thread, and the Go program does not want to handle it (that is, the | |
409 | // program has not called os/signal.Notify for the signal). | |
410 | func raisebadsignal(sig uint32, c *sigctxt) { | |
411 | if sig == _SIGPROF { | |
412 | // Ignore profiling signals that arrive on non-Go threads. | |
413 | return | |
414 | } | |
415 | ||
416 | var handler uintptr | |
417 | if sig >= _NSIG { | |
418 | handler = _SIG_DFL | |
419 | } else { | |
e104cab8 | 420 | handler = atomic.Loaduintptr(&fwdSig[sig]) |
ccea2b36 | 421 | } |
422 | ||
423 | // Reset the signal handler and raise the signal. | |
424 | // We are currently running inside a signal handler, so the | |
425 | // signal is blocked. We need to unblock it before raising the | |
426 | // signal, or the signal we raise will be ignored until we return | |
427 | // from the signal handler. We know that the signal was unblocked | |
428 | // before entering the handler, or else we would not have received | |
429 | // it. That means that we don't have to worry about blocking it | |
430 | // again. | |
431 | unblocksig(sig) | |
432 | setsig(sig, handler) | |
433 | ||
434 | // If we're linked into a non-Go program we want to try to | |
435 | // avoid modifying the original context in which the signal | |
436 | // was raised. If the handler is the default, we know it | |
437 | // is non-recoverable, so we don't have to worry about | |
438 | // re-installing sighandler. At this point we can just | |
439 | // return and the signal will be re-raised and caught by | |
440 | // the default handler with the correct context. | |
b0751b12 | 441 | // |
442 | // On FreeBSD, the libthr sigaction code prevents | |
443 | // this from working so we fall through to raise. | |
0e0a52c4 | 444 | // |
445 | // The argument above doesn't hold for SIGPIPE, which won't | |
446 | // necessarily be re-raised if we return. | |
447 | if GOOS != "freebsd" && (isarchive || islibrary) && handler == _SIG_DFL && c.sigcode() != _SI_USER && sig != _SIGPIPE { | |
ccea2b36 | 448 | return |
449 | } | |
450 | ||
451 | raise(sig) | |
452 | ||
453 | // Give the signal a chance to be delivered. | |
454 | // In almost all real cases the program is about to crash, | |
455 | // so sleeping here is not a waste of time. | |
456 | usleep(1000) | |
457 | ||
458 | // If the signal didn't cause the program to exit, restore the | |
459 | // Go signal handler and carry on. | |
460 | // | |
461 | // We may receive another instance of the signal before we | |
462 | // restore the Go handler, but that is not so bad: we know | |
463 | // that the Go program has been ignoring the signal. | |
464 | setsig(sig, getSigtramp()) | |
465 | } | |
466 | ||
b0751b12 | 467 | //go:nosplit |
ccea2b36 | 468 | func crash() { |
469 | if GOOS == "darwin" { | |
470 | // OS X core dumps are linear dumps of the mapped memory, | |
471 | // from the first virtual byte to the last, with zeros in the gaps. | |
472 | // Because of the way we arrange the address space on 64-bit systems, | |
473 | // this means the OS X core file will be >128 GB and even on a zippy | |
474 | // workstation can take OS X well over an hour to write (uninterruptible). | |
475 | // Save users from making that mistake. | |
33d1d391 | 476 | if GOARCH == "amd64" { |
ccea2b36 | 477 | return |
478 | } | |
479 | } | |
480 | ||
481 | dieFromSignal(_SIGABRT) | |
482 | } | |
483 | ||
484 | // ensureSigM starts one global, sleeping thread to make sure at least one thread | |
485 | // is available to catch signals enabled for os/signal. | |
486 | func ensureSigM() { | |
487 | if maskUpdatedChan != nil { | |
488 | return | |
489 | } | |
490 | maskUpdatedChan = make(chan struct{}) | |
491 | disableSigChan = make(chan uint32) | |
492 | enableSigChan = make(chan uint32) | |
493 | go func() { | |
494 | // Signal masks are per-thread, so make sure this goroutine stays on one | |
495 | // thread. | |
496 | LockOSThread() | |
497 | defer UnlockOSThread() | |
498 | // The sigBlocked mask contains the signals not active for os/signal, | |
499 | // initially all signals except the essential. When signal.Notify()/Stop is called, | |
500 | // sigenable/sigdisable in turn notify this thread to update its signal | |
501 | // mask accordingly. | |
502 | var sigBlocked sigset | |
503 | sigfillset(&sigBlocked) | |
504 | for i := range sigtable { | |
33d1d391 | 505 | if !blockableSig(uint32(i)) { |
ccea2b36 | 506 | sigdelset(&sigBlocked, i) |
507 | } | |
508 | } | |
509 | sigprocmask(_SIG_SETMASK, &sigBlocked, nil) | |
510 | for { | |
511 | select { | |
512 | case sig := <-enableSigChan: | |
513 | if sig > 0 { | |
514 | sigdelset(&sigBlocked, int(sig)) | |
515 | } | |
516 | case sig := <-disableSigChan: | |
33d1d391 | 517 | if sig > 0 && blockableSig(sig) { |
ccea2b36 | 518 | sigaddset(&sigBlocked, int(sig)) |
519 | } | |
520 | } | |
521 | sigprocmask(_SIG_SETMASK, &sigBlocked, nil) | |
522 | maskUpdatedChan <- struct{}{} | |
523 | } | |
524 | }() | |
525 | } | |
526 | ||
527 | // This is called when we receive a signal when there is no signal stack. | |
528 | // This can only happen if non-Go code calls sigaltstack to disable the | |
529 | // signal stack. | |
530 | func noSignalStack(sig uint32) { | |
531 | println("signal", sig, "received on thread with no signal stack") | |
532 | throw("non-Go code disabled sigaltstack") | |
533 | } | |
534 | ||
535 | // This is called if we receive a signal when there is a signal stack | |
536 | // but we are not on it. This can only happen if non-Go code called | |
537 | // sigaction without setting the SS_ONSTACK flag. | |
538 | func sigNotOnStack(sig uint32) { | |
539 | println("signal", sig, "received but handler not on signal stack") | |
540 | throw("non-Go code set up signal handler without SA_ONSTACK flag") | |
541 | } | |
542 | ||
e104cab8 | 543 | // signalDuringFork is called if we receive a signal while doing a fork. |
544 | // We do not want signals at that time, as a signal sent to the process | |
545 | // group may be delivered to the child process, causing confusion. | |
546 | // This should never be called, because we block signals across the fork; | |
547 | // this function is just a safety check. See issue 18600 for background. | |
548 | func signalDuringFork(sig uint32) { | |
549 | println("signal", sig, "received during fork") | |
550 | throw("signal received during fork") | |
551 | } | |
552 | ||
ccea2b36 | 553 | // This runs on a foreign stack, without an m or a g. No stack split. |
554 | //go:nosplit | |
555 | //go:norace | |
556 | //go:nowritebarrierrec | |
557 | func badsignal(sig uintptr, c *sigctxt) { | |
558 | needm(0) | |
559 | if !sigsend(uint32(sig)) { | |
560 | // A foreign thread received the signal sig, and the | |
561 | // Go code does not want to handle it. | |
562 | raisebadsignal(uint32(sig), c) | |
563 | } | |
564 | dropm() | |
565 | } | |
566 | ||
567 | // Determines if the signal should be handled by Go and if not, forwards the | |
568 | // signal to the handler that was installed before Go's. Returns whether the | |
569 | // signal was forwarded. | |
570 | // This is called by the signal handler, and the world may be stopped. | |
571 | //go:nosplit | |
572 | //go:nowritebarrierrec | |
ae306c0a | 573 | func sigfwdgo(sig uint32, info *_siginfo_t, ctx unsafe.Pointer) bool { |
ccea2b36 | 574 | if sig >= uint32(len(sigtable)) { |
575 | return false | |
576 | } | |
e104cab8 | 577 | fwdFn := atomic.Loaduintptr(&fwdSig[sig]) |
33d1d391 | 578 | flags := sigtable[sig].flags |
ccea2b36 | 579 | |
33d1d391 | 580 | // If we aren't handling the signal, forward it. |
581 | if atomic.Load(&handlingSig[sig]) == 0 || !signalsOK { | |
582 | // If the signal is ignored, doing nothing is the same as forwarding. | |
583 | if fwdFn == _SIG_IGN || (fwdFn == _SIG_DFL && flags&_SigIgn != 0) { | |
584 | return true | |
585 | } | |
586 | // We are not handling the signal and there is no other handler to forward to. | |
587 | // Crash with the default behavior. | |
ccea2b36 | 588 | if fwdFn == _SIG_DFL { |
33d1d391 | 589 | setsig(sig, _SIG_DFL) |
ccea2b36 | 590 | dieFromSignal(sig) |
33d1d391 | 591 | return false |
ccea2b36 | 592 | } |
33d1d391 | 593 | |
594 | sigfwd(fwdFn, sig, info, ctx) | |
ccea2b36 | 595 | return true |
596 | } | |
597 | ||
ccea2b36 | 598 | // If there is no handler to forward to, no need to forward. |
599 | if fwdFn == _SIG_DFL { | |
600 | return false | |
601 | } | |
602 | ||
ccea2b36 | 603 | c := sigctxt{info, ctx} |
e104cab8 | 604 | // Only forward synchronous signals and SIGPIPE. |
605 | // Unfortunately, user generated SIGPIPEs will also be forwarded, because si_code | |
606 | // is set to _SI_USER even for a SIGPIPE raised from a write to a closed socket | |
607 | // or pipe. | |
608 | if (c.sigcode() == _SI_USER || flags&_SigPanic == 0) && sig != _SIGPIPE { | |
ccea2b36 | 609 | return false |
610 | } | |
611 | // Determine if the signal occurred inside Go code. We test that: | |
612 | // (1) we were in a goroutine (i.e., m.curg != nil), and | |
e104cab8 | 613 | // (2) we weren't in CGO. |
ccea2b36 | 614 | g := getg() |
e104cab8 | 615 | if g != nil && g.m != nil && g.m.curg != nil && !g.m.incgo { |
ccea2b36 | 616 | return false |
617 | } | |
e104cab8 | 618 | |
ccea2b36 | 619 | // Signal not handled by Go, forward it. |
620 | if fwdFn != _SIG_IGN { | |
621 | sigfwd(fwdFn, sig, info, ctx) | |
622 | } | |
e104cab8 | 623 | |
ccea2b36 | 624 | return true |
625 | } | |
626 | ||
627 | // msigsave saves the current thread's signal mask into mp.sigmask. | |
628 | // This is used to preserve the non-Go signal mask when a non-Go | |
629 | // thread calls a Go function. | |
630 | // This is nosplit and nowritebarrierrec because it is called by needm | |
631 | // which may be called on a non-Go thread with no g available. | |
632 | //go:nosplit | |
633 | //go:nowritebarrierrec | |
634 | func msigsave(mp *m) { | |
635 | sigprocmask(_SIG_SETMASK, nil, &mp.sigmask) | |
636 | } | |
637 | ||
638 | // msigrestore sets the current thread's signal mask to sigmask. | |
639 | // This is used to restore the non-Go signal mask when a non-Go thread | |
640 | // calls a Go function. | |
641 | // This is nosplit and nowritebarrierrec because it is called by dropm | |
642 | // after g has been cleared. | |
643 | //go:nosplit | |
644 | //go:nowritebarrierrec | |
645 | func msigrestore(sigmask sigset) { | |
646 | sigprocmask(_SIG_SETMASK, &sigmask, nil) | |
647 | } | |
648 | ||
649 | // sigblock blocks all signals in the current thread's signal mask. | |
650 | // This is used to block signals while setting up and tearing down g | |
651 | // when a non-Go thread calls a Go function. | |
652 | // The OS-specific code is expected to define sigset_all. | |
653 | // This is nosplit and nowritebarrierrec because it is called by needm | |
654 | // which may be called on a non-Go thread with no g available. | |
655 | //go:nosplit | |
656 | //go:nowritebarrierrec | |
657 | func sigblock() { | |
658 | var set sigset | |
659 | sigfillset(&set) | |
660 | sigprocmask(_SIG_SETMASK, &set, nil) | |
661 | } | |
662 | ||
663 | // unblocksig removes sig from the current thread's signal mask. | |
664 | // This is nosplit and nowritebarrierrec because it is called from | |
665 | // dieFromSignal, which can be called by sigfwdgo while running in the | |
666 | // signal handler, on the signal stack, with no g available. | |
667 | //go:nosplit | |
668 | //go:nowritebarrierrec | |
669 | func unblocksig(sig uint32) { | |
670 | var set sigset | |
671 | sigemptyset(&set) | |
672 | sigaddset(&set, int(sig)) | |
673 | sigprocmask(_SIG_UNBLOCK, &set, nil) | |
674 | } | |
675 | ||
676 | // minitSignals is called when initializing a new m to set the | |
677 | // thread's alternate signal stack and signal mask. | |
678 | func minitSignals() { | |
679 | minitSignalStack() | |
680 | minitSignalMask() | |
681 | } | |
682 | ||
683 | // minitSignalStack is called when initializing a new m to set the | |
684 | // alternate signal stack. If the alternate signal stack is not set | |
685 | // for the thread (the normal case) then set the alternate signal | |
686 | // stack to the gsignal stack. If the alternate signal stack is set | |
687 | // for the thread (the case when a non-Go thread sets the alternate | |
688 | // signal stack and then calls a Go function) then set the gsignal | |
689 | // stack to the alternate signal stack. Record which choice was made | |
690 | // in newSigstack, so that it can be undone in unminit. | |
691 | func minitSignalStack() { | |
692 | _g_ := getg() | |
693 | var st _stack_t | |
694 | sigaltstack(nil, &st) | |
695 | if st.ss_flags&_SS_DISABLE != 0 { | |
696 | signalstack(_g_.m.gsignalstack, _g_.m.gsignalstacksize) | |
697 | _g_.m.newSigstack = true | |
698 | } else { | |
699 | _g_.m.newSigstack = false | |
700 | } | |
701 | } | |
702 | ||
703 | // minitSignalMask is called when initializing a new m to set the | |
704 | // thread's signal mask. When this is called all signals have been | |
705 | // blocked for the thread. This starts with m.sigmask, which was set | |
706 | // either from initSigmask for a newly created thread or by calling | |
707 | // msigsave if this is a non-Go thread calling a Go function. It | |
708 | // removes all essential signals from the mask, thus causing those | |
709 | // signals to not be blocked. Then it sets the thread's signal mask. | |
710 | // After this is called the thread can receive signals. | |
711 | func minitSignalMask() { | |
712 | nmask := getg().m.sigmask | |
713 | for i := range sigtable { | |
33d1d391 | 714 | if !blockableSig(uint32(i)) { |
ccea2b36 | 715 | sigdelset(&nmask, i) |
716 | } | |
717 | } | |
718 | sigprocmask(_SIG_SETMASK, &nmask, nil) | |
719 | } | |
720 | ||
721 | // unminitSignals is called from dropm, via unminit, to undo the | |
722 | // effect of calling minit on a non-Go thread. | |
723 | //go:nosplit | |
4822bb39 | 724 | //go:nowritebarrierrec |
ccea2b36 | 725 | func unminitSignals() { |
726 | if getg().m.newSigstack { | |
727 | signalstack(nil, 0) | |
728 | } | |
729 | } | |
33d1d391 | 730 | |
31975c5e | 731 | // blockableSig reports whether sig may be blocked by the signal mask. |
33d1d391 | 732 | // We never want to block the signals marked _SigUnblock; |
733 | // these are the synchronous signals that turn into a Go panic. | |
734 | // In a Go program--not a c-archive/c-shared--we never want to block | |
735 | // the signals marked _SigKill or _SigThrow, as otherwise it's possible | |
736 | // for all running threads to block them and delay their delivery until | |
737 | // we start a new thread. When linked into a C program we let the C code | |
738 | // decide on the disposition of those signals. | |
739 | func blockableSig(sig uint32) bool { | |
740 | flags := sigtable[sig].flags | |
741 | if flags&_SigUnblock != 0 { | |
742 | return false | |
743 | } | |
744 | if isarchive || islibrary { | |
745 | return true | |
746 | } | |
747 | return flags&(_SigKill|_SigThrow) == 0 | |
748 | } |