OLD | NEW |
| (Empty) |
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 #include "runtime.h" | |
6 #include "defs_GOOS_GOARCH.h" | |
7 #include "signals_GOOS.h" | |
8 #include "os_GOOS.h" | |
9 | |
10 extern void runtime·sigtramp(void); | |
11 | |
12 typedef struct sigaction { | |
13 union { | |
14 void (*__sa_handler)(int32); | |
15 void (*__sa_sigaction)(int32, Siginfo*, void *); | |
16 } __sigaction_u; /* signal handler */ | |
17 uint32 sa_mask; /* signal mask to apply */ | |
18 int32 sa_flags; /* see signal options below */ | |
19 } Sigaction; | |
20 | |
21 void | |
22 runtime·dumpregs(Sigcontext *r) | |
23 { | |
24 runtime·printf("eax %x\n", r->sc_eax); | |
25 runtime·printf("ebx %x\n", r->sc_ebx); | |
26 runtime·printf("ecx %x\n", r->sc_ecx); | |
27 runtime·printf("edx %x\n", r->sc_edx); | |
28 runtime·printf("edi %x\n", r->sc_edi); | |
29 runtime·printf("esi %x\n", r->sc_esi); | |
30 runtime·printf("ebp %x\n", r->sc_ebp); | |
31 runtime·printf("esp %x\n", r->sc_esp); | |
32 runtime·printf("eip %x\n", r->sc_eip); | |
33 runtime·printf("eflags %x\n", r->sc_eflags); | |
34 runtime·printf("cs %x\n", r->sc_cs); | |
35 runtime·printf("fs %x\n", r->sc_fs); | |
36 runtime·printf("gs %x\n", r->sc_gs); | |
37 } | |
38 | |
39 void | |
40 runtime·sighandler(int32 sig, Siginfo *info, void *context, G *gp) | |
41 { | |
42 Sigcontext *r = context; | |
43 uintptr *sp; | |
44 SigTab *t; | |
45 | |
46 if(sig == SIGPROF) { | |
47 runtime·sigprof((uint8*)r->sc_eip, (uint8*)r->sc_esp, nil, gp); | |
48 return; | |
49 } | |
50 | |
51 t = &runtime·sigtab[sig]; | |
52 if(info->si_code != SI_USER && (t->flags & SigPanic)) { | |
53 if(gp == nil || gp == m->g0) | |
54 goto Throw; | |
55 // Make it look like a call to the signal func. | |
56 // Have to pass arguments out of band since | |
57 // augmenting the stack frame would break | |
58 // the unwinding code. | |
59 gp->sig = sig; | |
60 gp->sigcode0 = info->si_code; | |
61 gp->sigcode1 = *(uintptr*)((byte*)info + 12); /* si_addr */ | |
62 gp->sigpc = r->sc_eip; | |
63 | |
64 // Only push runtime·sigpanic if r->sc_eip != 0. | |
65 // If r->sc_eip == 0, probably panicked because of a | |
66 // call to a nil func. Not pushing that onto sp will | |
67 // make the trace look like a call to runtime·sigpanic instead. | |
68 // (Otherwise the trace will end at runtime·sigpanic and we | |
69 // won't get to see who faulted.) | |
70 if(r->sc_eip != 0) { | |
71 sp = (uintptr*)r->sc_esp; | |
72 *--sp = r->sc_eip; | |
73 r->sc_esp = (uintptr)sp; | |
74 } | |
75 r->sc_eip = (uintptr)runtime·sigpanic; | |
76 return; | |
77 } | |
78 | |
79 if(info->si_code == SI_USER || (t->flags & SigNotify)) | |
80 if(runtime·sigsend(sig)) | |
81 return; | |
82 if(t->flags & SigKill) | |
83 runtime·exit(2); | |
84 if(!(t->flags & SigThrow)) | |
85 return; | |
86 | |
87 Throw: | |
88 runtime·startpanic(); | |
89 | |
90 if(sig < 0 || sig >= NSIG) | |
91 runtime·printf("Signal %d\n", sig); | |
92 else | |
93 runtime·printf("%s\n", runtime·sigtab[sig].name); | |
94 | |
95 runtime·printf("PC=%X\n", r->sc_eip); | |
96 if(m->lockedg != nil && m->ncgo > 0 && gp == m->g0) { | |
97 runtime·printf("signal arrived during cgo execution\n"); | |
98 gp = m->lockedg; | |
99 } | |
100 runtime·printf("\n"); | |
101 | |
102 if(runtime·gotraceback()){ | |
103 runtime·traceback((void*)r->sc_eip, (void*)r->sc_esp, 0, gp); | |
104 runtime·tracebackothers(gp); | |
105 runtime·dumpregs(r); | |
106 } | |
107 | |
108 runtime·exit(2); | |
109 } | |
110 | |
111 void | |
112 runtime·signalstack(byte *p, int32 n) | |
113 { | |
114 Sigaltstack st; | |
115 | |
116 st.ss_sp = p; | |
117 st.ss_size = n; | |
118 st.ss_flags = 0; | |
119 if(p == nil) | |
120 st.ss_flags = SS_DISABLE; | |
121 runtime·sigaltstack(&st, nil); | |
122 } | |
123 | |
124 void | |
125 runtime·setsig(int32 i, void (*fn)(int32, Siginfo*, void*, G*), bool restart) | |
126 { | |
127 Sigaction sa; | |
128 | |
129 // If SIGHUP handler is SIG_IGN, assume running | |
130 // under nohup and do not set explicit handler. | |
131 if(i == SIGHUP) { | |
132 runtime·memclr((byte*)&sa, sizeof sa); | |
133 runtime·sigaction(i, nil, &sa); | |
134 if(sa.__sigaction_u.__sa_sigaction == SIG_IGN) | |
135 return; | |
136 } | |
137 | |
138 runtime·memclr((byte*)&sa, sizeof sa); | |
139 sa.sa_flags = SA_SIGINFO|SA_ONSTACK; | |
140 if(restart) | |
141 sa.sa_flags |= SA_RESTART; | |
142 sa.sa_mask = ~0ULL; | |
143 if (fn == runtime·sighandler) | |
144 fn = (void*)runtime·sigtramp; | |
145 sa.__sigaction_u.__sa_sigaction = (void*)fn; | |
146 runtime·sigaction(i, &sa, nil); | |
147 } | |
OLD | NEW |