2011-10-08 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / runtime / go-signal.c
blobc16b058b79e4bd85f0ecc2ae2a2c728398a72e9c
1 /* go-signal.c -- signal handling for Go.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <sys/time.h>
11 #include "go-assert.h"
12 #include "go-panic.h"
13 #include "go-signal.h"
15 #include "runtime.h"
17 #ifndef SA_RESTART
18 #define SA_RESTART 0
19 #endif
21 /* What to do for a signal. */
23 struct sigtab
25 /* Signal number. */
26 int sig;
27 /* Nonzero if the signal should be ignored. */
28 _Bool ignore;
29 /* Nonzero if we should restart system calls. */
30 _Bool restart;
33 /* What to do for signals. */
35 static struct sigtab signals[] =
37 { SIGHUP, 0, 1 },
38 { SIGINT, 0, 1 },
39 { SIGALRM, 1, 1 },
40 { SIGTERM, 0, 1 },
41 #ifdef SIGBUS
42 { SIGBUS, 0, 0 },
43 #endif
44 #ifdef SIGFPE
45 { SIGFPE, 0, 0 },
46 #endif
47 #ifdef SIGUSR1
48 { SIGUSR1, 1, 1 },
49 #endif
50 #ifdef SIGSEGV
51 { SIGSEGV, 0, 0 },
52 #endif
53 #ifdef SIGUSR2
54 { SIGUSR2, 1, 1 },
55 #endif
56 #ifdef SIGPIPE
57 { SIGPIPE, 1, 0 },
58 #endif
59 #ifdef SIGCHLD
60 { SIGCHLD, 1, 1 },
61 #endif
62 #ifdef SIGTSTP
63 { SIGTSTP, 1, 1 },
64 #endif
65 #ifdef SIGTTIN
66 { SIGTTIN, 1, 1 },
67 #endif
68 #ifdef SIGTTOU
69 { SIGTTOU, 1, 1 },
70 #endif
71 #ifdef SIGURG
72 { SIGURG, 1, 1 },
73 #endif
74 #ifdef SIGXCPU
75 { SIGXCPU, 1, 1 },
76 #endif
77 #ifdef SIGXFSZ
78 { SIGXFSZ, 1, 1 },
79 #endif
80 #ifdef SIGVTARLM
81 { SIGVTALRM, 1, 1 },
82 #endif
83 #ifdef SIGWINCH
84 { SIGWINCH, 1, 1 },
85 #endif
86 #ifdef SIGIO
87 { SIGIO, 1, 1 },
88 #endif
89 #ifdef SIGPWR
90 { SIGPWR, 1, 1 },
91 #endif
92 { -1, 0, 0 }
95 /* The Go signal handler. */
97 static void
98 sighandler (int sig)
100 const char *msg;
101 int i;
103 if (sig == SIGPROF)
105 /* FIXME. */
106 runtime_sigprof (0, 0, nil);
107 return;
110 /* FIXME: Should check siginfo for more information when
111 available. */
112 msg = NULL;
113 switch (sig)
115 #ifdef SIGBUS
116 case SIGBUS:
117 msg = "invalid memory address or nil pointer dereference";
118 break;
119 #endif
121 #ifdef SIGFPE
122 case SIGFPE:
123 msg = "integer divide by zero or floating point error";
124 break;
125 #endif
127 #ifdef SIGSEGV
128 case SIGSEGV:
129 msg = "invalid memory address or nil pointer dereference";
130 break;
131 #endif
133 default:
134 break;
137 if (msg != NULL)
139 sigset_t clear;
141 if (__sync_bool_compare_and_swap (&m->mallocing, 1, 1))
143 fprintf (stderr, "caught signal while mallocing: %s\n", msg);
144 __go_assert (0);
147 /* The signal handler blocked signals; unblock them. */
148 i = sigfillset (&clear);
149 __go_assert (i == 0);
150 i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
151 __go_assert (i == 0);
153 __go_panic_msg (msg);
156 if (__go_sigsend (sig))
157 return;
158 for (i = 0; signals[i].sig != -1; ++i)
160 if (signals[i].sig == sig)
162 struct sigaction sa;
164 if (signals[i].ignore)
165 return;
167 memset (&sa, 0, sizeof sa);
169 sa.sa_handler = SIG_DFL;
171 i = sigemptyset (&sa.sa_mask);
172 __go_assert (i == 0);
174 if (sigaction (sig, &sa, NULL) != 0)
175 abort ();
177 raise (sig);
178 exit (2);
181 abort ();
184 /* Initialize signal handling for Go. This is called when the program
185 starts. */
187 void
188 __initsig ()
190 struct sigaction sa;
191 int i;
193 siginit ();
195 memset (&sa, 0, sizeof sa);
197 sa.sa_handler = sighandler;
199 i = sigfillset (&sa.sa_mask);
200 __go_assert (i == 0);
202 for (i = 0; signals[i].sig != -1; ++i)
204 sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
205 if (sigaction (signals[i].sig, &sa, NULL) != 0)
206 __go_assert (0);
210 void
211 runtime_resetcpuprofiler(int32 hz)
213 struct itimerval it;
214 struct sigaction sa;
215 int i;
217 memset (&it, 0, sizeof it);
219 memset (&sa, 0, sizeof sa);
220 i = sigfillset (&sa.sa_mask);
221 __go_assert (i == 0);
223 if (hz == 0)
225 i = setitimer (ITIMER_PROF, &it, NULL);
226 __go_assert (i == 0);
228 sa.sa_handler = SIG_IGN;
229 i = sigaction (SIGPROF, &sa, NULL);
230 __go_assert (i == 0);
232 else
234 sa.sa_handler = sighandler;
235 sa.sa_flags = SA_RESTART;
236 i = sigaction (SIGPROF, &sa, NULL);
237 __go_assert (i == 0);
239 it.it_interval.tv_sec = 0;
240 it.it_interval.tv_usec = 1000000 / hz;
241 it.it_value = it.it_interval;
242 i = setitimer (ITIMER_PROF, &it, NULL);
243 __go_assert (i == 0);
246 m->profilehz = hz;
249 /* Used by the os package to raise SIGPIPE. */
251 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
253 void
254 os_sigpipe (void)
256 struct sigaction sa;
257 int i;
259 memset (&sa, 0, sizeof sa);
261 sa.sa_handler = SIG_DFL;
263 i = sigemptyset (&sa.sa_mask);
264 __go_assert (i == 0);
266 if (sigaction (SIGPIPE, &sa, NULL) != 0)
267 abort ();
269 raise (SIGPIPE);