ptr CreateCo(VoidFnPtr function, WORD size) { Coroutine *newco; struct sigaction act_save, act_new; struct sigstack stack_save, stack_new; sigset_t set_save, set_new; void (*fn)(int); newco = (Coroutine *) malloc (sizeof(Coroutine)); if (newco == NULL) return (NULL); Dbg(("CreateCo: new coroutine is at %x", newco)); Dbg(("CreateCo: saving current state in %x", CurrentCo->JmpBuf)); if (sigsetjmp((sigjmp_buf *) CurrentCo->JmpBuf, 1) == 0) { newco->Parent = CurrentCo; CurrentCo = newco; /* Block all signals except SIGUSR1 */ sigfillset(&set_new); sigdelset(&set_new, SIGUSR1); sigprocmask(SIG_SETMASK, &set_new, &set_save); /* Set up the coroutine stack as the signal handling stack */ stack_new.ss_sp = (caddr_t) &(newco->Stack[STK_SIZE - sizeof(int)]); stack_new.ss_onstack = 0; sigstack(&stack_new, &stack_save); /* Install the signal handling routine. */ sigaction(SIGUSR1, NULL, &act_save); act_new.sa_handler = createco_aux; act_new.sa_mask = act_save.sa_mask; act_new.sa_flags = act_save.sa_flags | SA_ONSTACK; sigaction(SIGUSR1, &act_new, NULL); Dbg(("CreateCo: raising signal to activate new coroutine %x", newco)); /* Now get the coroutine running. */ raise(SIGUSR1); } else { /* createco_aux has done the siglongjmp... */ /* switch back to default signal stack */ sigstack(&stack_save, NULL); /* restore the signal handler. */ sigaction(SIGUSR1, &act_save, NULL); /* and unblock the various signals. */ sigprocmask(SIG_SETMASK, &set_save, NULL); /* restore CurrentCo */ CurrentCo = CurrentCo->Parent; Dbg(("CreateCo: new coroutine has been initialised, CurrentCo %x", CurrentCo)); } Dbg(("CreateCo: returning new coroutine %x", newco)); return(newco); }
void osinit(void) { #ifdef OREO set42sig(); setcompat(getcompat() & ~COMPAT_EXEC); signal(SIGIO, SIG_IGN); /* ignore SIGIO */ #endif /* OREO */ #ifdef aiws { struct sigstack inst; inst.ss_sp = xmalloc(4192) + 4192; inst.ss_onstack = 0; sigstack(&inst, NULL); } #endif /* aiws */ #ifdef apollo (void) isapad(); #endif #ifdef _SX /* * kill(SIGCONT) problems, don't know what this syscall does * [[email protected]] */ syscall(151, getpid(), getpid()); #endif /* _SX */ }
void SignalInterface::init_signal_stack() { // ensure generic val is enough for ppc signal_stack_size = max(1 << 15, SIGSTKSZ); // 32K should be enough signal_stack = (char*)valloc(signal_stack_size); struct sigstack ss; ss.ss_sp = signal_stack + signal_stack_size; // stack grows downwards ss.ss_onstack = false; if (sigstack(&ss, NULL) == -1) { perror("sigstack"); fatal("cannot install signal stack"); } }
/*---------------------------------------------------------------------+ | main () | | ==================================================================== | | | | Function: Main program (see prolog for more details) | | | +---------------------------------------------------------------------*/ int main(int argc, char **argv) { sigset_t mask, /* Initial process signal mask */ newmask, /* Second process signal mask */ oldmask; /* Signal mask returned by sigblock */ pid_t pid = getpid(); /* Process ID (of this process) */ /* Print out program header */ printf("%s: IPC Signals TestSuite program\n\n", *argv); /* * Establish signal handler for each signal & reset "valid signals" * array, and setup alternative stack for processing signals */ init_sig_vec(); reset_valid_sig(); #ifdef _LINUX_ // sigstack function is obsolete, use sigaltstack instead if (sigaltstack(&stack, NULL) < 0) sys_error("sigaltstack failed", __LINE__); #else if (sigstack(&stack, NULL) < 0) sys_error("sigstack failed", __LINE__); #endif /* * Send SIGILL, SIGALRM & SIGIOT signals to this process: * * First indicate which signals the signal handler should expect * by setting the corresponding valid_sig[] array fields. * * Then send the signals to this process. * * And finally verify that the signals were caught by the signal * handler by checking to see if the corresponding valid_sig[] array * fields were reset. */ printf("\tSend SIGILL, SIGALRM, SIGIOT signals to process\n"); valid_sig[SIGILL] = 1; valid_sig[SIGALRM] = 1; valid_sig[SIGIOT] = 1; kill(pid, SIGILL); kill(pid, SIGALRM); kill(pid, SIGIOT); if (valid_sig[SIGILL]) error("failed to receive SIGILL signal!", __LINE__); if (valid_sig[SIGALRM]) error("failed to receive SIGALRM signal!", __LINE__); if (valid_sig[SIGIOT]) error("failed to receive SIGIOT signal!", __LINE__); /* * Block SIGILL, SIGALRM & SIGIOT signals: * * First create the process signal mask by ORing together the * signal values. * * Then change the process signal mask with sigsetmask (). * * Verify that the desired signals are blocked from interrupting the * process, by sending both blocked and unblocked signals to the * process. Only the unblocked signals should interrupt the process. */ printf("\n\tBlock SIGILL, SIGALRM, SIGIOT signals, " "and resend signals + others\n"); sigemptyset(&mask); sigaddset(&mask, SIGILL); sigaddset(&mask, SIGALRM); sigaddset(&mask, SIGIOT); #ifdef _LINUX_ sigprocmask(SIG_SETMASK, &mask, NULL); #else if (sigsetmask(mask) < 0) sys_error("setsigmask failed", __LINE__); #endif valid_sig[SIGFPE] = 1; valid_sig[SIGTERM] = 1; valid_sig[SIGINT] = 1; kill(pid, SIGILL); kill(pid, SIGALRM); kill(pid, SIGIOT); kill(pid, SIGFPE); kill(pid, SIGTERM); kill(pid, SIGINT); if (valid_sig[SIGFPE]) error("failed to receive SIGFPE signal!", __LINE__); if (valid_sig[SIGTERM]) error("failed to receive SIGTERM signal!", __LINE__); if (valid_sig[SIGINT]) error("failed to receive SIGINT signal!", __LINE__); /* * Block additional SIGFPE, SIGTERM & SIGINT signals: * * Create a signal mask containing the additional signals to block. * * Change the process signal mask to block the additional signals * with the sigprocmask () function. * * Verify that all of the desired signals are now blocked from * interrupting the process. None of the specified signals should * interrupt the process until the process signal mask is changed. */ printf("\n\tBlock rest of signals\n"); sigemptyset(&newmask); sigaddset(&newmask, SIGFPE); sigaddset(&newmask, SIGTERM); sigaddset(&newmask, SIGINT); sigemptyset(&oldmask); if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { perror("sigprocmask failed"); exit(-1); } if (memcmp(&mask, &oldmask, sizeof(mask)) != 0) error("value returned by sigblock () does not match the " "old signal mask", __LINE__); kill(pid, SIGILL); kill(pid, SIGALRM); kill(pid, SIGIOT); kill(pid, SIGFPE); kill(pid, SIGTERM); kill(pid, SIGINT); /* Wait two seconds just to make sure that none of the specified * signals interrupt the process (They should all be blocked). */ sleep(2); /* Change the process signal mask: * * Now allow the SIGINT signal to interrupt the process. * Thus by using sigpause (), force the process to suspend * execution until delivery of an unblocked signal (here SIGINT). * * Additionally, verify that the SIGINT signal was received. */ valid_sig[SIGINT] = 1; printf ("\n\tChange signal mask & wait until signal interrupts process\n"); if (sigpause(SIGINT) != -1 || errno != 4) sys_error("sigpause failed", __LINE__); if (valid_sig[SIGINT]) error("failed to receive SIGINT signal!", __LINE__); /* Program completed successfully -- exit */ printf("\nsuccessful!\n"); return (0); }
static int co_set_context(co_ctx_t *ctx, void *func, char *stkbase, long stksiz) { struct sigaction sa; struct sigaction osa; sigset_t osigs; sigset_t sigs; #if defined(CO_HAS_SIGSTACK) struct sigstack ss; struct sigstack oss; #elif defined(CO_HAS_SIGALTSTACK) struct sigaltstack ss; struct sigaltstack oss; #else #error "PCL: Unknown context stack type" #endif /* * Preserve the SIGUSR1 signal state, block SIGUSR1, * and establish our signal handler. The signal will * later transfer control onto the signal stack. */ sigemptyset(&sigs); sigaddset(&sigs, SIGUSR1); sigprocmask(SIG_BLOCK, &sigs, &osigs); sa.sa_handler = co_ctx_trampoline; sigemptyset(&sa.sa_mask); sa.sa_flags = SA_ONSTACK; if (sigaction(SIGUSR1, &sa, &osa) != 0) return -1; /* * Set the new stack. * * For sigaltstack we're lucky [from sigaltstack(2) on * FreeBSD 3.1]: ``Signal stacks are automatically adjusted * for the direction of stack growth and alignment * requirements'' * * For sigstack we have to decide ourself [from sigstack(2) * on Solaris 2.6]: ``The direction of stack growth is not * indicated in the historical definition of struct sigstack. * The only way to portably establish a stack pointer is for * the application to determine stack growth direction.'' */ #if defined(CO_HAS_SIGALTSTACK) ss.ss_sp = stkbase; ss.ss_size = stksiz - sizeof(long); ss.ss_flags = 0; if (sigaltstack(&ss, &oss) < 0) return -1; #elif defined(CO_HAS_SIGSTACK) if (co_ctx_stackdir() < 0) ss.ss_sp = (stkbase + stksiz - sizeof(long)); else ss.ss_sp = stkbase; ss.ss_onstack = 0; if (sigstack(&ss, &oss) < 0) return -1; #else #error "PCL: Unknown context stack type" #endif /* * Now transfer control onto the signal stack and set it up. * It will return immediately via "return" after the setjmp() * was performed. Be careful here with race conditions. The * signal can be delivered the first time sigsuspend() is * called. */ ctx_called = 0; kill(getpid(), SIGUSR1); sigfillset(&sigs); sigdelset(&sigs, SIGUSR1); while (!ctx_called) sigsuspend(&sigs); /* * Inform the system that we are back off the signal stack by * removing the alternative signal stack. Be careful here: It * first has to be disabled, before it can be removed. */ #if defined(CO_HAS_SIGALTSTACK) sigaltstack(NULL, &ss); ss.ss_flags = SS_DISABLE; if (sigaltstack(&ss, NULL) < 0) return -1; sigaltstack(NULL, &ss); if (!(ss.ss_flags & SS_DISABLE)) return -1; if (!(oss.ss_flags & SS_DISABLE)) sigaltstack(&oss, NULL); #elif defined(CO_HAS_SIGSTACK) if (sigstack(&oss, NULL)) return -1; #else #error "PCL: Unknown context stack type" #endif /* * Restore the old SIGUSR1 signal handler and mask */ sigaction(SIGUSR1, &osa, NULL); sigprocmask(SIG_SETMASK, &osigs, NULL); /* * Set creation information. */ ctx_creating = ctx; ctx_creating_func = func; memcpy(&ctx_creating_sigs, &osigs, sizeof(sigset_t)); /* * Now enter the trampoline again, but this time not as a signal * handler. Instead we jump into it directly. */ if (setjmp(ctx_caller.cc) == 0) longjmp(ctx_trampoline.cc, 1); return 0; }
void setup_error_handler (void) { #if HAVE_SIGACTION struct sigaction act; act.sa_handler = cleanup_and_exit; sigemptyset (&(act.sa_mask)); #define SIGNAL(sig) sigaction (sig, &act, NULL) #else struct { int sa_flags; } act; #define SIGNAL(sig) signal (sig, cleanup_and_exit) #endif act.sa_flags = 0; /* Set up a stack for signal handling. A typical cause of error is stack overflow, and in such situation a signal can not be delivered on the overflown stack. */ #if HAVE_SIGALTSTACK { /* AIX uses stack_t, MacOS uses struct sigaltstack, various other systems have both. */ #if HAVE_STACK_T stack_t s; #else struct sigaltstack s; #endif s.ss_sp = malloc (SIGSTKSZ); s.ss_size = SIGSTKSZ; s.ss_flags = 0; if (sigaltstack (&s, NULL) != 0) perror("sigaltstack"); act.sa_flags = SA_ONSTACK; } #else #if HAVE_SIGSTACK { struct sigstack s; s.ss_sp = malloc (SIGSTKSZ); if (stack_downwards_p ()) s.ss_sp += SIGSTKSZ; s.ss_onstack = 0; if (sigstack (&s, NULL) != 0) perror("sigstack"); act.sa_flags = SA_ONSTACK; } #else #endif #endif #ifdef LIMIT_RESOURCE_USAGE { struct rlimit limit; limit.rlim_cur = limit.rlim_max = 0; setrlimit (RLIMIT_CORE, &limit); limit.rlim_cur = 3; limit.rlim_max = 4; setrlimit (RLIMIT_CPU, &limit); limit.rlim_cur = limit.rlim_max = 16 * 1024 * 1024; setrlimit (RLIMIT_DATA, &limit); getrlimit (RLIMIT_STACK, &limit); limit.rlim_cur = 4 * 1024 * 1024; setrlimit (RLIMIT_STACK, &limit); SIGNAL (SIGXCPU); } #endif /* LIMIT_RESOURCE_USAGE */ SIGNAL (SIGILL); SIGNAL (SIGSEGV); #ifdef SIGBUS /* not in mingw */ SIGNAL (SIGBUS); #endif SIGNAL (SIGFPE); SIGNAL (SIGABRT); }
int main(int argc, char *argv[]) { FILE *f; char *skaddr; char *skbuf; int sksize; char result[1024]; int i; sksize = 32768; skbuf = (char *) malloc(sksize * 2 + 2 * sizeof(union alltypes)); if (skbuf == NULL) exit(1); for (i = 0; i < sksize * 2 + 2 * sizeof(union alltypes); i++) skbuf[i] = 'A'; skaddr = skbuf + sizeof(union alltypes); #if defined(TEST_sigstack) || defined(TEST_sigaltstack) { struct sigaction sa; #if defined(TEST_sigstack) struct sigstack ss; #elif defined(TEST_sigaltstack) && defined(HAVE_STACK_T) stack_t ss; #else struct sigaltstack ss; #endif #if defined(TEST_sigstack) ss.ss_sp = (void *) (skaddr + sksize); ss.ss_onstack = 0; if (sigstack(&ss, NULL) < 0) exit(1); #elif defined(TEST_sigaltstack) ss.ss_sp = (void *) (skaddr + sksize); ss.ss_size = sksize; ss.ss_flags = 0; if (sigaltstack(&ss, NULL) < 0) exit(1); #endif memset((void *) &sa, 0, sizeof(struct sigaction)); sa.sa_handler = handler; sa.sa_flags = SA_ONSTACK; sigemptyset(&sa.sa_mask); sigaction(SIGUSR1, &sa, NULL); kill(getpid(), SIGUSR1); while (!handler_done) /*nop */ ; } #endif #if defined(TEST_makecontext) { if (getcontext(&uc_handler) != 0) exit(1); uc_handler.uc_link = NULL; uc_handler.uc_stack.ss_sp = (void *) (skaddr + sksize); uc_handler.uc_stack.ss_size = sksize; uc_handler.uc_stack.ss_flags = 0; makecontext(&uc_handler, handler, 0); swapcontext(&uc_main, &uc_handler); } #endif if (handler_addr == (char *) 0xDEAD) exit(1); if (handler_addr < skaddr + sksize) { /* stack was placed into lower area */ if (*(skaddr + sksize) != 'A') sprintf(result, "(skaddr)+(sksize)-%d,(sksize)-%d", sizeof(union alltypes), sizeof(union alltypes)); else strcpy(result, "(skaddr)+(sksize),(sksize)"); } else { /* stack was placed into higher area */ if (*(skaddr + sksize * 2) != 'A') sprintf(result, "(skaddr),(sksize)-%d", sizeof(union alltypes)); else strcpy(result, "(skaddr),(sksize)"); } if ((f = fopen("conftestval", "w")) == NULL) exit(1); fprintf(f, "%s\n", result); fclose(f); exit(0); return 1; }