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)
|
||||
{
|
||||
__printpanics (p->__next);
|
||||
printf ("\t");
|
||||
fprintf (stderr, "\t");
|
||||
}
|
||||
printf ("panic: ");
|
||||
fprintf (stderr, "panic: ");
|
||||
printany (p->__arg);
|
||||
if (p->__was_recovered)
|
||||
printf (" [recovered]");
|
||||
putchar ('\n');
|
||||
fprintf (stderr, " [recovered]");
|
||||
fputc ('\n', stderr);
|
||||
}
|
||||
|
||||
/* This implements __go_panic which is used for the panic
|
||||
|
@ -17,109 +17,133 @@
|
||||
#define SA_RESTART 0
|
||||
#endif
|
||||
|
||||
/* What to do for a signal. */
|
||||
#ifdef USING_SPLIT_STACK
|
||||
|
||||
struct sigtab
|
||||
{
|
||||
/* 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;
|
||||
};
|
||||
extern void __splitstack_getcontext(void *context[10]);
|
||||
|
||||
/* What to do for signals. */
|
||||
extern void __splitstack_setcontext(void *context[10]);
|
||||
|
||||
static struct sigtab signals[] =
|
||||
{
|
||||
{ SIGHUP, 0, 1, 0, 1 },
|
||||
{ SIGINT, 0, 1, 0, 1 },
|
||||
{ SIGQUIT, 0, 1, 0, 1 },
|
||||
{ SIGALRM, 0, 1, 1, 1 },
|
||||
{ SIGTERM, 0, 1, 0, 1 },
|
||||
#endif
|
||||
|
||||
#define C SigCatch
|
||||
#define I SigIgnore
|
||||
#define R SigRestart
|
||||
#define Q SigQueue
|
||||
#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
|
||||
{ SIGILL, 1, 0, 0, 0 },
|
||||
{ SIGILL, C },
|
||||
#endif
|
||||
#ifdef SIGTRAP
|
||||
{ SIGTRAP, 1, 0, 0, 0 },
|
||||
{ SIGTRAP, C },
|
||||
#endif
|
||||
#ifdef SIGABRT
|
||||
{ SIGABRT, 1, 0, 0, 0 },
|
||||
{ SIGABRT, C },
|
||||
#endif
|
||||
#ifdef SIGBUS
|
||||
{ SIGBUS, 1, 0, 0, 0 },
|
||||
{ SIGBUS, C + P },
|
||||
#endif
|
||||
#ifdef SIGFPE
|
||||
{ SIGFPE, 1, 0, 0, 0 },
|
||||
{ SIGFPE, C + P },
|
||||
#endif
|
||||
#ifdef SIGUSR1
|
||||
{ SIGUSR1, 0, 1, 1, 1 },
|
||||
{ SIGUSR1, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGSEGV
|
||||
{ SIGSEGV, 1, 0, 0, 0 },
|
||||
{ SIGSEGV, C + P },
|
||||
#endif
|
||||
#ifdef SIGUSR2
|
||||
{ SIGUSR2, 0, 1, 1, 1 },
|
||||
{ SIGUSR2, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGPIPE
|
||||
{ SIGPIPE, 0, 0, 1, 0 },
|
||||
{ SIGPIPE, I },
|
||||
#endif
|
||||
#ifdef SIGALRM
|
||||
{ SIGALRM, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGTERM
|
||||
{ SIGTERM, Q + R },
|
||||
#endif
|
||||
#ifdef SIGSTKFLT
|
||||
{ SIGSTKFLT, 1, 0, 0, 0 },
|
||||
{ SIGSTKFLT, C },
|
||||
#endif
|
||||
#ifdef SIGCHLD
|
||||
{ SIGCHLD, 0, 1, 1, 1 },
|
||||
{ SIGCHLD, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGTSTP
|
||||
{ SIGTSTP, 0, 1, 1, 1 },
|
||||
{ SIGTSTP, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGTTIN
|
||||
{ SIGTTIN, 0, 1, 1, 1 },
|
||||
{ SIGTTIN, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGTTOU
|
||||
{ SIGTTOU, 0, 1, 1, 1 },
|
||||
{ SIGTTOU, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGURG
|
||||
{ SIGURG, 0, 1, 1, 1 },
|
||||
{ SIGURG, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGXCPU
|
||||
{ SIGXCPU, 0, 1, 1, 1 },
|
||||
{ SIGXCPU, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGXFSZ
|
||||
{ SIGXFSZ, 0, 1, 1, 1 },
|
||||
{ SIGXFSZ, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGVTARLM
|
||||
{ SIGVTALRM, 0, 1, 1, 1 },
|
||||
#ifdef SIGVTALRM
|
||||
{ SIGVTALRM, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGPROF
|
||||
{ SIGPROF, 0, 1, 1, 1 },
|
||||
{ SIGPROF, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGWINCH
|
||||
{ SIGWINCH, 0, 1, 1, 1 },
|
||||
{ SIGWINCH, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGIO
|
||||
{ SIGIO, 0, 1, 1, 1 },
|
||||
{ SIGIO, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGPWR
|
||||
{ SIGPWR, 0, 1, 1, 1 },
|
||||
{ SIGPWR, Q + I + R },
|
||||
#endif
|
||||
#ifdef SIGSYS
|
||||
{ SIGSYS, 1, 0, 0, 0 },
|
||||
{ SIGSYS, C },
|
||||
#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
|
||||
sighandler (int sig)
|
||||
sig_handler (int sig)
|
||||
{
|
||||
const char *msg;
|
||||
int i;
|
||||
|
||||
#ifdef SIGPROF
|
||||
@ -131,99 +155,223 @@ sighandler (int sig)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* FIXME: Should check siginfo for more information when
|
||||
available. */
|
||||
msg = NULL;
|
||||
for (i = 0; runtime_sigtab[i].sig != -1; ++i)
|
||||
{
|
||||
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)
|
||||
{
|
||||
#ifdef SIGILL
|
||||
case SIGILL:
|
||||
msg = "illegal instruction";
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIGBUS
|
||||
case SIGBUS:
|
||||
msg = "invalid memory address or nil pointer dereference";
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef SIGFPE
|
||||
case SIGFPE:
|
||||
msg = "integer divide by zero or floating point error";
|
||||
break;
|
||||
if (info->si_code == BUS_ADRERR && (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
|
||||
|
||||
#ifdef SIGSEGV
|
||||
case SIGSEGV:
|
||||
msg = "invalid memory address or nil pointer dereference";
|
||||
break;
|
||||
if ((info->si_code == 0
|
||||
|| 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
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg != NULL)
|
||||
{
|
||||
sigset_t clear;
|
||||
|
||||
if (runtime_m()->mallocing)
|
||||
#ifdef SIGFPE
|
||||
case SIGFPE:
|
||||
switch (info->si_code)
|
||||
{
|
||||
fprintf (stderr, "caught signal while mallocing: %s\n", msg);
|
||||
__go_assert (0);
|
||||
case FPE_INTDIV:
|
||||
runtime_panicstring ("integer divide by zero");
|
||||
case FPE_INTOVF:
|
||||
runtime_panicstring ("integer overflow");
|
||||
}
|
||||
|
||||
/* The signal handler blocked signals; unblock them. */
|
||||
i = sigfillset (&clear);
|
||||
__go_assert (i == 0);
|
||||
i = sigprocmask (SIG_UNBLOCK, &clear, NULL);
|
||||
__go_assert (i == 0);
|
||||
|
||||
runtime_panicstring (msg);
|
||||
runtime_panicstring ("floating point error");
|
||||
#endif
|
||||
}
|
||||
|
||||
for (i = 0; signals[i].sig != -1; ++i)
|
||||
{
|
||||
if (signals[i].sig == sig)
|
||||
{
|
||||
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 ();
|
||||
/* All signals with SigPanic should be in cases above, and this
|
||||
handler should only be invoked for those signals. */
|
||||
__builtin_unreachable ();
|
||||
}
|
||||
|
||||
/* 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
|
||||
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
|
||||
starts. */
|
||||
|
||||
@ -237,21 +385,44 @@ runtime_initsig (int32 queue)
|
||||
|
||||
memset (&sa, 0, sizeof sa);
|
||||
|
||||
sa.sa_handler = sighandler;
|
||||
|
||||
i = sigfillset (&sa.sa_mask);
|
||||
__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;
|
||||
if (signals[i].catch || signals[i].queue)
|
||||
sa.sa_handler = sighandler;
|
||||
if ((runtime_sigtab[i].flags & SigQueue) != queue)
|
||||
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
|
||||
sa.sa_handler = sig_ignore;
|
||||
sa.sa_flags = signals[i].restart ? SA_RESTART : 0;
|
||||
if (sigaction (signals[i].sig, &sa, NULL) != 0)
|
||||
{
|
||||
sa.sa_flags = SA_ONSTACK;
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -281,7 +452,7 @@ runtime_resetcpuprofiler(int32 hz)
|
||||
}
|
||||
else
|
||||
{
|
||||
sa.sa_handler = sighandler;
|
||||
sa.sa_handler = sig_handler;
|
||||
sa.sa_flags = SA_RESTART;
|
||||
i = sigaction (SIGPROF, &sa, NULL);
|
||||
__go_assert (i == 0);
|
||||
|
@ -47,7 +47,7 @@ runtime_SysAlloc(uintptr n)
|
||||
if (dev_zero == -1) {
|
||||
dev_zero = open("/dev/zero", O_RDONLY);
|
||||
if (dev_zero < 0) {
|
||||
printf("open /dev/zero: errno=%d\n", errno);
|
||||
runtime_printf("open /dev/zero: errno=%d\n", errno);
|
||||
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);
|
||||
if (p == MAP_FAILED) {
|
||||
if(errno == EACCES) {
|
||||
printf("runtime: mmap: access denied\n");
|
||||
printf("if you're running SELinux, enable execmem for this process.\n");
|
||||
runtime_printf("runtime: mmap: access denied\n");
|
||||
runtime_printf("if you're running SELinux, enable execmem for this process.\n");
|
||||
exit(2);
|
||||
}
|
||||
return nil;
|
||||
@ -97,7 +97,7 @@ runtime_SysReserve(void *v, uintptr n)
|
||||
if (dev_zero == -1) {
|
||||
dev_zero = open("/dev/zero", O_RDONLY);
|
||||
if (dev_zero < 0) {
|
||||
printf("open /dev/zero: errno=%d\n", errno);
|
||||
runtime_printf("open /dev/zero: errno=%d\n", errno);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
@ -123,7 +123,7 @@ runtime_SysMap(void *v, uintptr n)
|
||||
if (dev_zero == -1) {
|
||||
dev_zero = open("/dev/zero", O_RDONLY);
|
||||
if (dev_zero < 0) {
|
||||
printf("open /dev/zero: errno=%d\n", errno);
|
||||
runtime_printf("open /dev/zero: errno=%d\n", errno);
|
||||
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 **,
|
||||
void **);
|
||||
|
||||
extern void __splitstack_block_signals (int *, int *);
|
||||
|
||||
extern void __splitstack_block_signals_context (void *context[10], int *,
|
||||
int *);
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(USING_SPLIT_STACK) && defined(LINKER_SUPPORTS_SPLIT_STACK)
|
||||
@ -862,6 +867,14 @@ runtime_mstart(void* mp)
|
||||
*(int*)0x21 = 0x21;
|
||||
}
|
||||
runtime_minit();
|
||||
|
||||
#ifdef USING_SPLIT_STACK
|
||||
{
|
||||
int dont_block_signals = 0;
|
||||
__splitstack_block_signals(&dont_block_signals, nil);
|
||||
}
|
||||
#endif
|
||||
|
||||
schedule(nil);
|
||||
return nil;
|
||||
}
|
||||
@ -1142,9 +1155,13 @@ runtime_malg(int32 stacksize, byte** ret_stack, size_t* ret_stacksize)
|
||||
newg = runtime_malloc(sizeof(G));
|
||||
if(stacksize >= 0) {
|
||||
#if USING_SPLIT_STACK
|
||||
int dont_block_signals = 0;
|
||||
|
||||
*ret_stack = __splitstack_makecontext(stacksize,
|
||||
&newg->stack_context[0],
|
||||
ret_stacksize);
|
||||
__splitstack_block_signals_context(&newg->stack_context[0],
|
||||
&dont_block_signals, nil);
|
||||
#else
|
||||
*ret_stack = runtime_mallocgc(stacksize, FlagNoProfiling|FlagNoGC, 0, 0);
|
||||
*ret_stacksize = stacksize;
|
||||
@ -1186,8 +1203,12 @@ __go_go(void (*fn)(void*), void* arg)
|
||||
|
||||
if((newg = gfget()) != nil){
|
||||
#ifdef USING_SPLIT_STACK
|
||||
int dont_block_signals = 0;
|
||||
|
||||
sp = __splitstack_resetcontext(&newg->stack_context[0],
|
||||
&spsize);
|
||||
__splitstack_block_signals_context(&newg->stack_context[0],
|
||||
&dont_block_signals, nil);
|
||||
#else
|
||||
sp = newg->gcinitial_sp;
|
||||
spsize = newg->gcstack_size;
|
||||
|
@ -52,6 +52,7 @@ typedef struct G G;
|
||||
typedef union Lock Lock;
|
||||
typedef struct M M;
|
||||
typedef union Note Note;
|
||||
typedef struct SigTab SigTab;
|
||||
typedef struct MCache MCache;
|
||||
typedef struct FixAlloc FixAlloc;
|
||||
typedef struct Hchan Hchan;
|
||||
@ -179,6 +180,20 @@ struct M
|
||||
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. */
|
||||
|
||||
#ifdef __WINDOWS__
|
||||
@ -251,7 +266,7 @@ void runtime_args(int32, byte**);
|
||||
void runtime_osinit();
|
||||
void runtime_goargs(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_mal(uintptr);
|
||||
void runtime_schedinit(void);
|
||||
|
@ -110,6 +110,6 @@ func Signame(sig int32) (name String) {
|
||||
}
|
||||
|
||||
func Siginit() {
|
||||
runtime_initsig(1);
|
||||
runtime_initsig(SigQueue);
|
||||
sig.inuse = true; // enable reception of signals; cannot disable
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user