OSDN Git Service

* config/i386/i386.md (*movdi_internal_rex64): Merge
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-signal.c
1 /* go-signal.c -- signal handling for Go.
2
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.  */
6
7 #include <signal.h>
8 #include <stdlib.h>
9 #include <sys/time.h>
10
11 #include "go-assert.h"
12 #include "go-panic.h"
13 #include "go-signal.h"
14
15 #include "runtime.h"
16
17 #ifndef SA_RESTART
18   #define SA_RESTART 0
19 #endif
20
21 /* What to do for a signal.  */
22
23 struct sigtab
24 {
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;
31 };
32
33 /* What to do for signals.  */
34
35 static struct sigtab signals[] =
36 {
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 }
93 };
94
95 /* The Go signal handler.  */
96
97 static void
98 sighandler (int sig)
99 {
100   const char *msg;
101   int i;
102
103   if (sig == SIGPROF)
104     {
105       /* FIXME.  */
106       runtime_sigprof (0, 0, nil);
107       return;
108     }
109
110   /* FIXME: Should check siginfo for more information when
111      available.  */
112   msg = NULL;
113   switch (sig)
114     {
115 #ifdef SIGBUS
116     case SIGBUS:
117       msg = "invalid memory address or nil pointer dereference";
118       break;
119 #endif
120
121 #ifdef SIGFPE
122     case SIGFPE:
123       msg = "integer divide by zero or floating point error";
124       break;
125 #endif
126
127 #ifdef SIGSEGV
128     case SIGSEGV:
129       msg = "invalid memory address or nil pointer dereference";
130       break;
131 #endif
132
133     default:
134       break;
135     }
136
137   if (msg != NULL)
138     {
139       sigset_t clear;
140
141       if (__sync_bool_compare_and_swap (&m->mallocing, 1, 1))
142         {
143           fprintf (stderr, "caught signal while mallocing: %s\n", msg);
144           __go_assert (0);
145         }
146
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);
152
153       __go_panic_msg (msg);
154     }
155
156   if (__go_sigsend (sig))
157     return;
158   for (i = 0; signals[i].sig != -1; ++i)
159     {
160       if (signals[i].sig == sig)
161         {
162           struct sigaction sa;
163
164           if (signals[i].ignore)
165             return;
166
167           memset (&sa, 0, sizeof sa);
168
169           sa.sa_handler = SIG_DFL;
170
171           i = sigemptyset (&sa.sa_mask);
172           __go_assert (i == 0);
173
174           if (sigaction (sig, &sa, NULL) != 0)
175             abort ();
176
177           raise (sig);
178           exit (2);
179         }
180     }
181   abort ();
182 }
183
184 /* Initialize signal handling for Go.  This is called when the program
185    starts.  */
186
187 void
188 __initsig ()
189 {
190   struct sigaction sa;
191   int i;
192
193   siginit ();
194
195   memset (&sa, 0, sizeof sa);
196
197   sa.sa_handler = sighandler;
198
199   i = sigfillset (&sa.sa_mask);
200   __go_assert (i == 0);
201
202   for (i = 0; signals[i].sig != -1; ++i)
203     {
204       sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
205       if (sigaction (signals[i].sig, &sa, NULL) != 0)
206         __go_assert (0);
207     }
208 }
209
210 void
211 runtime_resetcpuprofiler(int32 hz)
212 {
213   struct itimerval it;
214   struct sigaction sa;
215   int i;
216
217   memset (&it, 0, sizeof it);
218
219   memset (&sa, 0, sizeof sa);
220   i = sigfillset (&sa.sa_mask);
221   __go_assert (i == 0);
222
223   if (hz == 0)
224     {
225       i = setitimer (ITIMER_PROF, &it, NULL);
226       __go_assert (i == 0);
227
228       sa.sa_handler = SIG_IGN;
229       i = sigaction (SIGPROF, &sa, NULL);
230       __go_assert (i == 0);
231     }
232   else
233     {
234       sa.sa_handler = sighandler;
235       sa.sa_flags = SA_RESTART;
236       i = sigaction (SIGPROF, &sa, NULL);
237       __go_assert (i == 0);
238
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);
244     }
245
246   m->profilehz = hz;
247 }
248
249 /* Used by the os package to raise SIGPIPE.  */
250
251 void os_sigpipe (void) __asm__ ("libgo_os.os.sigpipe");
252
253 void
254 os_sigpipe (void)
255 {
256   struct sigaction sa;
257   int i;
258
259   memset (&sa, 0, sizeof sa);
260
261   sa.sa_handler = SIG_DFL;
262
263   i = sigemptyset (&sa.sa_mask);
264   __go_assert (i == 0);
265
266   if (sigaction (SIGPIPE, &sa, NULL) != 0)
267     abort ();
268
269   raise (SIGPIPE);
270 }