1 /* 2 * Copyright 2007, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include <errno.h> 8 #include <signal.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <unistd.h> 13 14 15 #if defined(__BEOS__) && !defined(__HAIKU__) 16 typedef void (*sighandler_t)(int); 17 # define SIGSTKSZ 16384 18 # define SA_ONESHOT 0 19 # define SA_ONSTACK 0 20 # define SA_RESTART 0 21 # define ualarm(usec, interval) alarm(1) 22 #endif 23 24 #if !defined(__USE_GNU) 25 // sighandler is a GNU extension. This matches the check 26 // in signal.h. We may want to use posix sigaction though 27 // in the future which is posix 28 typedef void (*sighandler_t)(int); 29 #endif 30 31 32 const void* kUserDataMagic = (void *)0x12345678; 33 34 static char sAlternateStack[SIGSTKSZ]; 35 36 37 bool 38 is_alternate(void* pointer) 39 { 40 return (char*)pointer > &sAlternateStack[0] 41 && (char*)pointer <= &sAlternateStack[0] + SIGSTKSZ; 42 } 43 44 45 void 46 sigHandler(int signal, void *userData, vregs *regs) 47 { 48 #if defined(__BEOS__) || defined(__HAIKU__) 49 if (userData != kUserDataMagic) 50 fprintf(stderr, "FAILED: user data not correct: %p\n", userData); 51 #endif 52 53 printf("signal handler called with signal %i on %s stack\n", 54 signal, is_alternate(&signal) ? "alternate" : "standard"); 55 } 56 57 58 void 59 wait_for_key() 60 { 61 char buffer[100]; 62 if (fgets(buffer, sizeof(buffer), stdin) == NULL 63 || buffer[0] == 'q') { 64 if (errno == EINTR) 65 puts("interrupted"); 66 else 67 exit(0); 68 } 69 } 70 71 int 72 main() 73 { 74 puts("-- 1 (should block) --"); 75 76 struct sigaction newAction; 77 newAction.sa_handler = (sighandler_t)sigHandler; 78 newAction.sa_mask = 0; 79 newAction.sa_flags = SA_ONESHOT | SA_ONSTACK | SA_RESTART; 80 #if defined(__BEOS__) || defined(__HAIKU__) 81 newAction.sa_userdata = (void*)kUserDataMagic; 82 #endif 83 sigaction(SIGALRM, &newAction, NULL); 84 85 ualarm(10000, 0); 86 wait_for_key(); 87 88 puts("-- 2 (does not block, should call handler twice) --"); 89 90 newAction.sa_flags = 0; 91 sigaction(SIGALRM, &newAction, NULL); 92 93 ualarm(0, 50000); 94 wait_for_key(); 95 wait_for_key(); 96 97 ualarm(0, 0); 98 99 puts("-- 3 (alternate stack, should block) --"); 100 101 #if defined(__BEOS__) && !defined(__HAIKU__) 102 set_signal_stack(sAlternateStack, SIGSTKSZ); 103 #else 104 stack_t newStack; 105 newStack.ss_sp = sAlternateStack; 106 newStack.ss_size = SIGSTKSZ; 107 newStack.ss_flags = 0; 108 if (sigaltstack(&newStack, NULL) != 0) 109 fprintf(stderr, "sigaltstack() failed: %s\n", strerror(errno)); 110 #endif 111 112 newAction.sa_flags = SA_RESTART | SA_ONSTACK; 113 sigaction(SIGALRM, &newAction, NULL); 114 115 ualarm(10000, 0); 116 wait_for_key(); 117 118 puts("-- end --"); 119 return 0; 120 } 121