mirror of git://gcc.gnu.org/git/gcc.git
runtime: Catch signals on altstack, disable splitstack signal blocking.
From-SVN: r182607
This commit is contained in:
parent
e0d2f03016
commit
a6dcb7d465
|
|
@ -24,13 +24,13 @@ __printpanics (struct __go_panic_stack *p)
|
||||||
if (p->__next != NULL)
|
if (p->__next != NULL)
|
||||||
{
|
{
|
||||||
__printpanics (p->__next);
|
__printpanics (p->__next);
|
||||||
printf ("\t");
|
fprintf (stderr, "\t");
|
||||||
}
|
}
|
||||||
printf ("panic: ");
|
fprintf (stderr, "panic: ");
|
||||||
printany (p->__arg);
|
printany (p->__arg);
|
||||||
if (p->__was_recovered)
|
if (p->__was_recovered)
|
||||||
printf (" [recovered]");
|
fprintf (stderr, " [recovered]");
|
||||||
putchar ('\n');
|
fputc ('\n', stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This implements __go_panic which is used for the panic
|
/* This implements __go_panic which is used for the panic
|
||||||
|
|
|
||||||
|
|
@ -17,109 +17,133 @@
|
||||||
#define SA_RESTART 0
|
#define SA_RESTART 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* What to do for a signal. */
|
#ifdef USING_SPLIT_STACK
|
||||||
|
|
||||||
struct sigtab
|
extern void __splitstack_getcontext(void *context[10]);
|
||||||
{
|
|
||||||
/* Signal number. */
|
|
||||||
int sig;
|
|
||||||
/* Nonzero if the signal should be caught. */
|
|
||||||
_Bool catch;
|
|
||||||
/* Nonzero if the signal should be queued. */
|
|
||||||
_Bool queue;
|
|
||||||
/* Nonzero if the signal should be ignored. */
|
|
||||||
_Bool ignore;
|
|
||||||
/* Nonzero if we should restart system calls. */
|
|
||||||
_Bool restart;
|
|
||||||
};
|
|
||||||
|
|
||||||
/* What to do for signals. */
|
extern void __splitstack_setcontext(void *context[10]);
|
||||||
|
|
||||||
static struct sigtab signals[] =
|
#endif
|
||||||
{
|
|
||||||
{ SIGHUP, 0, 1, 0, 1 },
|
#define C SigCatch
|
||||||
{ SIGINT, 0, 1, 0, 1 },
|
#define I SigIgnore
|
||||||
{ SIGQUIT, 0, 1, 0, 1 },
|
#define R SigRestart
|
||||||
{ SIGALRM, 0, 1, 1, 1 },
|
#define Q SigQueue
|
||||||
{ SIGTERM, 0, 1, 0, 1 },
|
#define P SigPanic
|
||||||
|
|
||||||
|
/* Signal actions. This collects the sigtab tables for several
|
||||||
|
different targets from the master library. SIGKILL, SIGCONT, and
|
||||||
|
SIGSTOP are not listed, as we don't want to set signal handlers for
|
||||||
|
them. */
|
||||||
|
|
||||||
|
SigTab runtime_sigtab[] = {
|
||||||
|
#ifdef SIGHUP
|
||||||
|
{ SIGHUP, Q + R },
|
||||||
|
#endif
|
||||||
|
#ifdef SIGINT
|
||||||
|
{ SIGINT, Q + R },
|
||||||
|
#endif
|
||||||
|
#ifdef SIGQUIT
|
||||||
|
{ SIGQUIT, C },
|
||||||
|
#endif
|
||||||
#ifdef SIGILL
|
#ifdef SIGILL
|
||||||
{ SIGILL, 1, 0, 0, 0 },
|
{ SIGILL, C },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGTRAP
|
#ifdef SIGTRAP
|
||||||
{ SIGTRAP, 1, 0, 0, 0 },
|
{ SIGTRAP, C },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGABRT
|
#ifdef SIGABRT
|
||||||
{ SIGABRT, 1, 0, 0, 0 },
|
{ SIGABRT, C },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGBUS
|
#ifdef SIGBUS
|
||||||
{ SIGBUS, 1, 0, 0, 0 },
|
{ SIGBUS, C + P },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGFPE
|
#ifdef SIGFPE
|
||||||
{ SIGFPE, 1, 0, 0, 0 },
|
{ SIGFPE, C + P },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGUSR1
|
#ifdef SIGUSR1
|
||||||
{ SIGUSR1, 0, 1, 1, 1 },
|
{ SIGUSR1, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGSEGV
|
#ifdef SIGSEGV
|
||||||
{ SIGSEGV, 1, 0, 0, 0 },
|
{ SIGSEGV, C + P },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGUSR2
|
#ifdef SIGUSR2
|
||||||
{ SIGUSR2, 0, 1, 1, 1 },
|
{ SIGUSR2, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGPIPE
|
#ifdef SIGPIPE
|
||||||
{ SIGPIPE, 0, 0, 1, 0 },
|
{ SIGPIPE, I },
|
||||||
|
#endif
|
||||||
|
#ifdef SIGALRM
|
||||||
|
{ SIGALRM, Q + I + R },
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTERM
|
||||||
|
{ SIGTERM, Q + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGSTKFLT
|
#ifdef SIGSTKFLT
|
||||||
{ SIGSTKFLT, 1, 0, 0, 0 },
|
{ SIGSTKFLT, C },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGCHLD
|
#ifdef SIGCHLD
|
||||||
{ SIGCHLD, 0, 1, 1, 1 },
|
{ SIGCHLD, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGTSTP
|
#ifdef SIGTSTP
|
||||||
{ SIGTSTP, 0, 1, 1, 1 },
|
{ SIGTSTP, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGTTIN
|
#ifdef SIGTTIN
|
||||||
{ SIGTTIN, 0, 1, 1, 1 },
|
{ SIGTTIN, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGTTOU
|
#ifdef SIGTTOU
|
||||||
{ SIGTTOU, 0, 1, 1, 1 },
|
{ SIGTTOU, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGURG
|
#ifdef SIGURG
|
||||||
{ SIGURG, 0, 1, 1, 1 },
|
{ SIGURG, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGXCPU
|
#ifdef SIGXCPU
|
||||||
{ SIGXCPU, 0, 1, 1, 1 },
|
{ SIGXCPU, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGXFSZ
|
#ifdef SIGXFSZ
|
||||||
{ SIGXFSZ, 0, 1, 1, 1 },
|
{ SIGXFSZ, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGVTARLM
|
#ifdef SIGVTALRM
|
||||||
{ SIGVTALRM, 0, 1, 1, 1 },
|
{ SIGVTALRM, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGPROF
|
#ifdef SIGPROF
|
||||||
{ SIGPROF, 0, 1, 1, 1 },
|
{ SIGPROF, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGWINCH
|
#ifdef SIGWINCH
|
||||||
{ SIGWINCH, 0, 1, 1, 1 },
|
{ SIGWINCH, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGIO
|
#ifdef SIGIO
|
||||||
{ SIGIO, 0, 1, 1, 1 },
|
{ SIGIO, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGPWR
|
#ifdef SIGPWR
|
||||||
{ SIGPWR, 0, 1, 1, 1 },
|
{ SIGPWR, Q + I + R },
|
||||||
#endif
|
#endif
|
||||||
#ifdef SIGSYS
|
#ifdef SIGSYS
|
||||||
{ SIGSYS, 1, 0, 0, 0 },
|
{ SIGSYS, C },
|
||||||
#endif
|
#endif
|
||||||
{ -1, 0, 0, 0, 0 }
|
#ifdef SIGEMT
|
||||||
|
{ SIGEMT, C },
|
||||||
|
#endif
|
||||||
|
#ifdef SIGINFO
|
||||||
|
{ SIGINFO, Q + I + R },
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTHR
|
||||||
|
{ SIGTHR, Q + I + R },
|
||||||
|
#endif
|
||||||
|
{ -1, 0 }
|
||||||
};
|
};
|
||||||
|
#undef C
|
||||||
|
#undef I
|
||||||
|
#undef R
|
||||||
|
#undef Q
|
||||||
|
#undef P
|
||||||
|
|
||||||
/* The Go signal handler. */
|
/* Handle a signal, for cases where we don't panic. We can split the
|
||||||
|
stack here. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sighandler (int sig)
|
sig_handler (int sig)
|
||||||
{
|
{
|
||||||
const char *msg;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
#ifdef SIGPROF
|
#ifdef SIGPROF
|
||||||
|
|
@ -131,99 +155,223 @@ sighandler (int sig)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* FIXME: Should check siginfo for more information when
|
for (i = 0; runtime_sigtab[i].sig != -1; ++i)
|
||||||
available. */
|
{
|
||||||
msg = NULL;
|
struct sigaction sa;
|
||||||
|
|
||||||
|
if (runtime_sigtab[i].sig != sig)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((runtime_sigtab[i].flags & SigQueue) != 0)
|
||||||
|
{
|
||||||
|
if (__go_sigsend (sig)
|
||||||
|
|| (runtime_sigtab[sig].flags & SigIgnore) != 0)
|
||||||
|
return;
|
||||||
|
runtime_exit (2); // SIGINT, SIGTERM, etc
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runtime_panicking)
|
||||||
|
runtime_exit (2);
|
||||||
|
runtime_panicking = 1;
|
||||||
|
|
||||||
|
/* We should do a stack backtrace here. Until we can do that,
|
||||||
|
we reraise the signal in order to get a slightly better
|
||||||
|
report from the shell. */
|
||||||
|
|
||||||
|
memset (&sa, 0, sizeof sa);
|
||||||
|
|
||||||
|
sa.sa_handler = SIG_DFL;
|
||||||
|
|
||||||
|
i = sigemptyset (&sa.sa_mask);
|
||||||
|
__go_assert (i == 0);
|
||||||
|
|
||||||
|
if (sigaction (sig, &sa, NULL) != 0)
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
raise (sig);
|
||||||
|
|
||||||
|
runtime_exit (2);
|
||||||
|
}
|
||||||
|
|
||||||
|
__builtin_unreachable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The start of handling a signal which panics. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_panic_leadin (int sig)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
sigset_t clear;
|
||||||
|
|
||||||
|
if (runtime_m ()->mallocing)
|
||||||
|
{
|
||||||
|
runtime_printf ("caught signal while mallocing: %d\n", sig);
|
||||||
|
runtime_throw ("caught signal while mallocing");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The signal handler blocked signals; unblock them. */
|
||||||
|
i = sigfillset (&clear);
|
||||||
|
__go_assert (i == 0);
|
||||||
|
i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
|
||||||
|
__go_assert (i == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef SA_SIGINFO
|
||||||
|
|
||||||
|
/* Signal dispatch for signals which panic, on systems which support
|
||||||
|
SA_SIGINFO. This is called on the thread stack, and as such it is
|
||||||
|
permitted to split the stack. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_panic_info_handler (int sig, siginfo_t *info,
|
||||||
|
void *context __attribute__ ((unused)))
|
||||||
|
{
|
||||||
|
if (runtime_g () == NULL)
|
||||||
|
{
|
||||||
|
sig_handler (sig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sig_panic_leadin (sig);
|
||||||
|
|
||||||
switch (sig)
|
switch (sig)
|
||||||
{
|
{
|
||||||
#ifdef SIGILL
|
|
||||||
case SIGILL:
|
|
||||||
msg = "illegal instruction";
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef SIGBUS
|
#ifdef SIGBUS
|
||||||
case SIGBUS:
|
case SIGBUS:
|
||||||
msg = "invalid memory address or nil pointer dereference";
|
if (info->si_code == BUS_ADRERR && (uintptr_t) info->si_addr < 0x1000)
|
||||||
break;
|
runtime_panicstring ("invalid memory address or "
|
||||||
#endif
|
"nil pointer dereference");
|
||||||
|
runtime_printf ("unexpected fault address %p\n", info->si_addr);
|
||||||
#ifdef SIGFPE
|
runtime_throw ("fault");
|
||||||
case SIGFPE:
|
|
||||||
msg = "integer divide by zero or floating point error";
|
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef SIGSEGV
|
#ifdef SIGSEGV
|
||||||
case SIGSEGV:
|
case SIGSEGV:
|
||||||
msg = "invalid memory address or nil pointer dereference";
|
if ((info->si_code == 0
|
||||||
break;
|
|| info->si_code == SEGV_MAPERR
|
||||||
|
|| info->si_code == SEGV_ACCERR)
|
||||||
|
&& (uintptr_t) info->si_addr < 0x1000)
|
||||||
|
runtime_panicstring ("invalid memory address or "
|
||||||
|
"nil pointer dereference");
|
||||||
|
runtime_printf ("unexpected fault address %p\n", info->si_addr);
|
||||||
|
runtime_throw ("fault");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
#ifdef SIGFPE
|
||||||
break;
|
case SIGFPE:
|
||||||
}
|
switch (info->si_code)
|
||||||
|
|
||||||
if (msg != NULL)
|
|
||||||
{
|
|
||||||
sigset_t clear;
|
|
||||||
|
|
||||||
if (runtime_m()->mallocing)
|
|
||||||
{
|
{
|
||||||
fprintf (stderr, "caught signal while mallocing: %s\n", msg);
|
case FPE_INTDIV:
|
||||||
__go_assert (0);
|
runtime_panicstring ("integer divide by zero");
|
||||||
|
case FPE_INTOVF:
|
||||||
|
runtime_panicstring ("integer overflow");
|
||||||
}
|
}
|
||||||
|
runtime_panicstring ("floating point error");
|
||||||
/* The signal handler blocked signals; unblock them. */
|
#endif
|
||||||
i = sigfillset (&clear);
|
|
||||||
__go_assert (i == 0);
|
|
||||||
i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
|
|
||||||
__go_assert (i == 0);
|
|
||||||
|
|
||||||
runtime_panicstring (msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; signals[i].sig != -1; ++i)
|
/* All signals with SigPanic should be in cases above, and this
|
||||||
{
|
handler should only be invoked for those signals. */
|
||||||
if (signals[i].sig == sig)
|
__builtin_unreachable ();
|
||||||
{
|
|
||||||
struct sigaction sa;
|
|
||||||
|
|
||||||
if (signals[i].queue)
|
|
||||||
{
|
|
||||||
if (__go_sigsend (sig) || signals[i].ignore)
|
|
||||||
return;
|
|
||||||
runtime_exit (2); // SIGINT, SIGTERM, etc
|
|
||||||
}
|
|
||||||
|
|
||||||
if (runtime_panicking)
|
|
||||||
runtime_exit (2);
|
|
||||||
runtime_panicking = 1;
|
|
||||||
|
|
||||||
memset (&sa, 0, sizeof sa);
|
|
||||||
|
|
||||||
sa.sa_handler = SIG_DFL;
|
|
||||||
|
|
||||||
i = sigemptyset (&sa.sa_mask);
|
|
||||||
__go_assert (i == 0);
|
|
||||||
|
|
||||||
if (sigaction (sig, &sa, NULL) != 0)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
raise (sig);
|
|
||||||
exit (2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
abort ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ignore a signal. */
|
#else /* !defined (SA_SIGINFO) */
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_panic_handler (int sig)
|
||||||
|
{
|
||||||
|
if (runtime_g () == NULL)
|
||||||
|
{
|
||||||
|
sig_handler (sig);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sig_panic_leadin (sig);
|
||||||
|
|
||||||
|
switch (sig)
|
||||||
|
{
|
||||||
|
#ifdef SIGBUS
|
||||||
|
case SIGBUS:
|
||||||
|
runtime_panicstring ("invalid memory address or "
|
||||||
|
"nil pointer dereference");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGSEGV
|
||||||
|
case SIGSEGV:
|
||||||
|
runtime_panicstring ("invalid memory address or "
|
||||||
|
"nil pointer dereference");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGFPE
|
||||||
|
case SIGFPE:
|
||||||
|
runtime_panicstring ("integer divide by zero or floating point error");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All signals with SigPanic should be in cases above, and this
|
||||||
|
handler should only be invoked for those signals. */
|
||||||
|
__builtin_unreachable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* !defined (SA_SIGINFO) */
|
||||||
|
|
||||||
|
/* Ignore a signal. This is called on the alternate signal stack so
|
||||||
|
it may not split the stack. */
|
||||||
|
|
||||||
|
static void sig_ignore (int) __attribute__ ((no_split_stack));
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sig_ignore (int sig __attribute__ ((unused)))
|
sig_ignore (int sig __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* A signal handler used for signals which are not going to panic.
|
||||||
|
This is called on the alternate signal stack so it may not split
|
||||||
|
the stack. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_tramp (int) __attribute__ ((no_split_stack));
|
||||||
|
|
||||||
|
static void
|
||||||
|
sig_tramp (int sig)
|
||||||
|
{
|
||||||
|
G *gp;
|
||||||
|
M *mp;
|
||||||
|
|
||||||
|
/* We are now running on the stack registered via sigaltstack.
|
||||||
|
(Actually there is a small span of time between runtime_siginit
|
||||||
|
and sigaltstack when the program starts.) */
|
||||||
|
gp = runtime_g ();
|
||||||
|
mp = runtime_m ();
|
||||||
|
|
||||||
|
if (gp != NULL)
|
||||||
|
__splitstack_getcontext (&gp->stack_context[0]);
|
||||||
|
|
||||||
|
if (gp != NULL && mp->gsignal != NULL)
|
||||||
|
{
|
||||||
|
/* We are running on the signal stack. Set the split stack
|
||||||
|
context so that the stack guards are checked correctly. */
|
||||||
|
#ifdef USING_SPLIT_STACK
|
||||||
|
__splitstack_setcontext (&mp->gsignal->stack_context[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
sig_handler (sig);
|
||||||
|
|
||||||
|
/* We are going to return back to the signal trampoline and then to
|
||||||
|
whatever we were doing before we got the signal. Restore the
|
||||||
|
split stack context so that stack guards are checked
|
||||||
|
correctly. */
|
||||||
|
|
||||||
|
if (gp != NULL)
|
||||||
|
{
|
||||||
|
#ifdef USING_SPLIT_STACK
|
||||||
|
__splitstack_setcontext (&gp->stack_context[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize signal handling for Go. This is called when the program
|
/* Initialize signal handling for Go. This is called when the program
|
||||||
starts. */
|
starts. */
|
||||||
|
|
||||||
|
|
@ -237,21 +385,44 @@ runtime_initsig (int32 queue)
|
||||||
|
|
||||||
memset (&sa, 0, sizeof sa);
|
memset (&sa, 0, sizeof sa);
|
||||||
|
|
||||||
sa.sa_handler = sighandler;
|
|
||||||
|
|
||||||
i = sigfillset (&sa.sa_mask);
|
i = sigfillset (&sa.sa_mask);
|
||||||
__go_assert (i == 0);
|
__go_assert (i == 0);
|
||||||
|
|
||||||
for (i = 0; signals[i].sig != -1; ++i)
|
for (i = 0; runtime_sigtab[i].sig != -1; ++i)
|
||||||
{
|
{
|
||||||
if (signals[i].queue != (queue ? 1 : 0))
|
if (runtime_sigtab[i].flags == 0)
|
||||||
continue;
|
continue;
|
||||||
if (signals[i].catch || signals[i].queue)
|
if ((runtime_sigtab[i].flags & SigQueue) != queue)
|
||||||
sa.sa_handler = sighandler;
|
continue;
|
||||||
|
|
||||||
|
if ((runtime_sigtab[i].flags & (SigCatch | SigQueue)) != 0)
|
||||||
|
{
|
||||||
|
if ((runtime_sigtab[i].flags & SigPanic) == 0)
|
||||||
|
{
|
||||||
|
sa.sa_flags = SA_ONSTACK;
|
||||||
|
sa.sa_handler = sig_tramp;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#ifdef SA_SIGINFO
|
||||||
|
sa.sa_flags = SA_SIGINFO;
|
||||||
|
sa.sa_sigaction = sig_panic_info_handler;
|
||||||
|
#else
|
||||||
|
sa.sa_flags = 0;
|
||||||
|
sa.sa_handler = sig_panic_handler;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sa.sa_handler = sig_ignore;
|
{
|
||||||
sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
|
sa.sa_flags = SA_ONSTACK;
|
||||||
if (sigaction (signals[i].sig, &sa, NULL) != 0)
|
sa.sa_handler = sig_ignore;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((runtime_sigtab[i].flags & SigRestart) != 0)
|
||||||
|
sa.sa_flags |= SA_RESTART;
|
||||||
|
|
||||||
|
if (sigaction (runtime_sigtab[i].sig, &sa, NULL) != 0)
|
||||||
__go_assert (0);
|
__go_assert (0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -281,7 +452,7 @@ runtime_resetcpuprofiler(int32 hz)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sa.sa_handler = sighandler;
|
sa.sa_handler = sig_handler;
|
||||||
sa.sa_flags = SA_RESTART;
|
sa.sa_flags = SA_RESTART;
|
||||||
i = sigaction (SIGPROF, &sa, NULL);
|
i = sigaction (SIGPROF, &sa, NULL);
|
||||||
__go_assert (i == 0);
|
__go_assert (i == 0);
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ runtime_SysAlloc(uintptr n)
|
||||||
if (dev_zero == -1) {
|
if (dev_zero == -1) {
|
||||||
dev_zero = open("/dev/zero", O_RDONLY);
|
dev_zero = open("/dev/zero", O_RDONLY);
|
||||||
if (dev_zero < 0) {
|
if (dev_zero < 0) {
|
||||||
printf("open /dev/zero: errno=%d\n", errno);
|
runtime_printf("open /dev/zero: errno=%d\n", errno);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -57,8 +57,8 @@ runtime_SysAlloc(uintptr n)
|
||||||
p = runtime_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
|
p = runtime_mmap(nil, n, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, fd, 0);
|
||||||
if (p == MAP_FAILED) {
|
if (p == MAP_FAILED) {
|
||||||
if(errno == EACCES) {
|
if(errno == EACCES) {
|
||||||
printf("runtime: mmap: access denied\n");
|
runtime_printf("runtime: mmap: access denied\n");
|
||||||
printf("if you're running SELinux, enable execmem for this process.\n");
|
runtime_printf("if you're running SELinux, enable execmem for this process.\n");
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
return nil;
|
return nil;
|
||||||
|
|
@ -97,7 +97,7 @@ runtime_SysReserve(void *v, uintptr n)
|
||||||
if (dev_zero == -1) {
|
if (dev_zero == -1) {
|
||||||
dev_zero = open("/dev/zero", O_RDONLY);
|
dev_zero = open("/dev/zero", O_RDONLY);
|
||||||
if (dev_zero < 0) {
|
if (dev_zero < 0) {
|
||||||
printf("open /dev/zero: errno=%d\n", errno);
|
runtime_printf("open /dev/zero: errno=%d\n", errno);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -123,7 +123,7 @@ runtime_SysMap(void *v, uintptr n)
|
||||||
if (dev_zero == -1) {
|
if (dev_zero == -1) {
|
||||||
dev_zero = open("/dev/zero", O_RDONLY);
|
dev_zero = open("/dev/zero", O_RDONLY);
|
||||||
if (dev_zero < 0) {
|
if (dev_zero < 0) {
|
||||||
printf("open /dev/zero: errno=%d\n", errno);
|
runtime_printf("open /dev/zero: errno=%d\n", errno);
|
||||||
exit(2);
|
exit(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,11 @@ extern void * __splitstack_resetcontext(void *context[10], size_t *);
|
||||||
extern void *__splitstack_find(void *, void *, size_t *, void **, void **,
|
extern void *__splitstack_find(void *, void *, size_t *, void **, void **,
|
||||||
void **);
|
void **);
|
||||||
|
|
||||||
|
extern void __splitstack_block_signals (int *, int *);
|
||||||
|
|
||||||
|
extern void __splitstack_block_signals_context (void *context[10], int *,
|
||||||
|
int *);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
|
#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
|
||||||
|
|
@ -862,6 +867,14 @@ runtime_mstart(void* mp)
|
||||||
*(int*)0x21 = 0x21;
|
*(int*)0x21 = 0x21;
|
||||||
}
|
}
|
||||||
runtime_minit();
|
runtime_minit();
|
||||||
|
|
||||||
|
#ifdef USING_SPLIT_STACK
|
||||||
|
{
|
||||||
|
int dont_block_signals = 0;
|
||||||
|
__splitstack_block_signals(&dont_block_signals, nil);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
schedule(nil);
|
schedule(nil);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
@ -1142,9 +1155,13 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
|
||||||
newg = runtime_malloc(sizeof(G));
|
newg = runtime_malloc(sizeof(G));
|
||||||
if(stacksize >= 0) {
|
if(stacksize >= 0) {
|
||||||
#if USING_SPLIT_STACK
|
#if USING_SPLIT_STACK
|
||||||
|
int dont_block_signals = 0;
|
||||||
|
|
||||||
*ret_stack = __splitstack_makecontext(stacksize,
|
*ret_stack = __splitstack_makecontext(stacksize,
|
||||||
&newg->stack_context[0],
|
&newg->stack_context[0],
|
||||||
ret_stacksize);
|
ret_stacksize);
|
||||||
|
__splitstack_block_signals_context(&newg->stack_context[0],
|
||||||
|
&dont_block_signals, nil);
|
||||||
#else
|
#else
|
||||||
*ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0);
|
*ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0);
|
||||||
*ret_stacksize = stacksize;
|
*ret_stacksize = stacksize;
|
||||||
|
|
@ -1186,8 +1203,12 @@ __go_go(void (*fn)(void*), void* arg)
|
||||||
|
|
||||||
if((newg = gfget()) != nil){
|
if((newg = gfget()) != nil){
|
||||||
#ifdef USING_SPLIT_STACK
|
#ifdef USING_SPLIT_STACK
|
||||||
|
int dont_block_signals = 0;
|
||||||
|
|
||||||
sp = __splitstack_resetcontext(&newg->stack_context[0],
|
sp = __splitstack_resetcontext(&newg->stack_context[0],
|
||||||
&spsize);
|
&spsize);
|
||||||
|
__splitstack_block_signals_context(&newg->stack_context[0],
|
||||||
|
&dont_block_signals, nil);
|
||||||
#else
|
#else
|
||||||
sp = newg->gcinitial_sp;
|
sp = newg->gcinitial_sp;
|
||||||
spsize = newg->gcstack_size;
|
spsize = newg->gcstack_size;
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ typedef struct G G;
|
||||||
typedef union Lock Lock;
|
typedef union Lock Lock;
|
||||||
typedef struct M M;
|
typedef struct M M;
|
||||||
typedef union Note Note;
|
typedef union Note Note;
|
||||||
|
typedef struct SigTab SigTab;
|
||||||
typedef struct MCache MCache;
|
typedef struct MCache MCache;
|
||||||
typedef struct FixAlloc FixAlloc;
|
typedef struct FixAlloc FixAlloc;
|
||||||
typedef struct Hchan Hchan;
|
typedef struct Hchan Hchan;
|
||||||
|
|
@ -179,6 +180,20 @@ struct M
|
||||||
uint32 waitsemalock;
|
uint32 waitsemalock;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SigTab
|
||||||
|
{
|
||||||
|
int32 sig;
|
||||||
|
int32 flags;
|
||||||
|
};
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
SigCatch = 1<<0,
|
||||||
|
SigIgnore = 1<<1,
|
||||||
|
SigRestart = 1<<2,
|
||||||
|
SigQueue = 1<<3,
|
||||||
|
SigPanic = 1<<4,
|
||||||
|
};
|
||||||
|
|
||||||
/* Macros. */
|
/* Macros. */
|
||||||
|
|
||||||
#ifdef __WINDOWS__
|
#ifdef __WINDOWS__
|
||||||
|
|
@ -251,7 +266,7 @@ void runtime_args(int32, byte**);
|
||||||
void runtime_osinit();
|
void runtime_osinit();
|
||||||
void runtime_goargs(void);
|
void runtime_goargs(void);
|
||||||
void runtime_goenvs(void);
|
void runtime_goenvs(void);
|
||||||
void runtime_throw(const char*);
|
void runtime_throw(const char*) __attribute__ ((noreturn));
|
||||||
void runtime_panicstring(const char*) __attribute__ ((noreturn));
|
void runtime_panicstring(const char*) __attribute__ ((noreturn));
|
||||||
void* runtime_mal(uintptr);
|
void* runtime_mal(uintptr);
|
||||||
void runtime_schedinit(void);
|
void runtime_schedinit(void);
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,6 @@ func Signame(sig int32) (name String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Siginit() {
|
func Siginit() {
|
||||||
runtime_initsig(1);
|
runtime_initsig(SigQueue);
|
||||||
sig.inuse = true; // enable reception of signals; cannot disable
|
sig.inuse = true; // enable reception of signals; cannot disable
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue