Changeset d3ce33fa in mainline for uspace/lib/posix/signal.c
- Timestamp:
- 2011-07-05T19:01:18Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- d9eaa43
- Parents:
- 4f86fa3
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/signal.c
r4f86fa3 rd3ce33fa 37 37 #include "signal.h" 38 38 #include "internal/common.h" 39 #include "limits.h" 40 #include "stdlib.h" 41 #include "string.h" 42 #include "errno.h" 43 44 #include "libc/fibril_synch.h" 45 #include "libc/task.h" 46 47 /* Used to serialize signal handling. */ 48 static FIBRIL_MUTEX_INITIALIZE(_signal_mutex); 49 50 static posix_sigset_t _signal_mask = 0; 51 52 #define DEFAULT_HANDLER { .sa_handler = SIG_DFL, \ 53 .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL } 54 55 static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = { 56 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 57 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 58 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 59 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 60 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 61 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 62 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER 63 }; 64 65 void __posix_default_signal_handler(int signo) 66 { 67 switch (signo) { 68 case SIGABRT: 69 abort(); 70 case SIGQUIT: 71 fprintf(stderr, "Quit signal raised. Exiting."); 72 exit(EXIT_FAILURE); 73 case SIGINT: 74 fprintf(stderr, "Interrupt signal caught. Exiting."); 75 exit(EXIT_FAILURE); 76 case SIGTERM: 77 fprintf(stderr, "Termination signal caught. Exiting."); 78 exit(EXIT_FAILURE); 79 case SIGSTOP: 80 fprintf(stderr, "Stop signal caught, but unsupported. Ignoring."); 81 break; 82 case SIGKILL: 83 /* This will only occur when raise or similar is called. */ 84 /* Commit suicide. */ 85 task_kill(task_get_id()); 86 87 /* Should not be reached. */ 88 abort(); 89 case SIGFPE: 90 case SIGBUS: 91 case SIGILL: 92 case SIGSEGV: 93 posix_psignal(signo, "Hardware exception raised by user code"); 94 abort(); 95 case SIGSYS: 96 case SIGXCPU: 97 case SIGXFSZ: 98 case SIGTRAP: 99 case SIGHUP: 100 case SIGPIPE: 101 case SIGPOLL: 102 case SIGURG: 103 case SIGTSTP: 104 case SIGTTIN: 105 case SIGTTOU: 106 posix_psignal(signo, "Unsupported signal caught"); 107 abort(); 108 case SIGCHLD: 109 case SIGUSR1: 110 case SIGUSR2: 111 case SIGALRM: 112 case SIGVTALRM: 113 case SIGPROF: 114 case SIGCONT: 115 /* ignored */ 116 break; 117 } 118 } 119 120 void __posix_hold_signal_handler(int signo) 121 { 122 /* Nothing */ 123 } 124 125 void __posix_ignore_signal_handler(int signo) 126 { 127 /* Nothing */ 128 } 129 130 131 int posix_sigemptyset(posix_sigset_t *set) 132 { 133 assert(set != NULL); 134 135 *set = 0; 136 return 0; 137 } 138 139 int posix_sigfillset(posix_sigset_t *set) 140 { 141 assert(set != NULL); 142 143 *set = UINT32_MAX; 144 return 0; 145 } 146 147 int posix_sigaddset(posix_sigset_t *set, int signo) 148 { 149 assert(set != NULL); 150 151 *set |= (1 << signo); 152 return 0; 153 } 154 155 int posix_sigdelset(posix_sigset_t *set, int signo) 156 { 157 assert(set != NULL); 158 159 *set &= ~(1 << signo); 160 return 0; 161 } 162 163 int posix_sigismember(const posix_sigset_t *set, int signo) 164 { 165 assert(set != NULL); 166 167 return (*set & (1 << signo)) != 0; 168 } 169 170 static void _sigaction_unsafe(int sig, const struct posix_sigaction *restrict act, 171 struct posix_sigaction *restrict oact) 172 { 173 if (oact != NULL) { 174 memcpy(oact, &_signal_actions[sig], 175 sizeof(struct posix_sigaction)); 176 } 177 178 if (act != NULL) { 179 memcpy(&_signal_actions[sig], act, 180 sizeof(struct posix_sigaction)); 181 } 182 } 183 184 int posix_sigaction(int sig, const struct posix_sigaction *restrict act, 185 struct posix_sigaction *restrict oact) 186 { 187 if (sig > _TOP_SIGNAL || (act != NULL && 188 (sig == SIGKILL || sig == SIGSTOP))) { 189 errno = EINVAL; 190 return -1; 191 } 192 193 if (sig > _TOP_CATCHABLE_SIGNAL) { 194 posix_psignal(sig, 195 "WARNING: registering handler for a partially" 196 " or fully unsupported signal. This handler may only be" 197 " invoked by the raise() function, which may not be what" 198 " the application developer intended.\nSignal name"); 199 } 200 201 fibril_mutex_lock(&_signal_mutex); 202 _sigaction_unsafe(sig, act, oact); 203 fibril_mutex_unlock(&_signal_mutex); 204 205 return 0; 206 } 39 207 40 208 void (*posix_signal(int sig, void (*func)(int)))(int) 41 209 { 42 // TODO 43 not_implemented(); 210 struct posix_sigaction new = { 211 .sa_handler = func, 212 .sa_mask = 0, 213 .sa_flags = 0, 214 .sa_sigaction = NULL 215 }; 216 struct posix_sigaction old; 217 if (posix_sigaction(sig, func == NULL ? NULL : &new, &old) == 0) { 218 return old.sa_handler; 219 } else { 220 return SIG_ERR; 221 } 222 } 223 224 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 225 { 226 assert(signo >= 0 && signo <= _TOP_SIGNAL); 227 assert(siginfo != NULL); 228 229 fibril_mutex_lock(&_signal_mutex); 230 231 struct posix_sigaction action = _signal_actions[signo]; 232 233 if (posix_sigismember(&_signal_mask, signo) || 234 action.sa_handler == SIG_HOLD) { 235 // TODO: queue signal 236 fibril_mutex_unlock(&_signal_mutex); 237 return -1; 238 } 239 240 /* Modifying signal mask is unnecessary, 241 * signal handling is serialized. 242 */ 243 244 if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) { 245 _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER; 246 }; 247 248 if (action.sa_flags & SA_SIGINFO) { 249 assert(action.sa_sigaction != NULL); 250 action.sa_sigaction(signo, siginfo, NULL); 251 } else { 252 assert(action.sa_handler != NULL); 253 action.sa_handler(signo); 254 } 255 256 fibril_mutex_unlock(&_signal_mutex); 257 258 return 0; 44 259 } 45 260 46 261 int posix_raise(int sig) 47 262 { 48 // TODO 49 not_implemented(); 50 } 51 52 int posix_kill(posix_pid_t pid, int sig) 53 { 54 // TODO 55 not_implemented(); 56 } 57 58 int posix_sigaddset(posix_sigset_t *set, int signo) 59 { 60 // TODO 61 not_implemented(); 62 } 63 64 int posix_sigemptyset(posix_sigset_t *set) 65 { 66 // TODO 67 not_implemented(); 263 if (sig >= 0 && sig <= _TOP_SIGNAL) { 264 posix_siginfo_t siginfo = { 265 .si_signo = sig, 266 .si_code = SI_USER 267 }; 268 return _raise_sigaction(sig, &siginfo); 269 } else { 270 errno = EINVAL; 271 return -1; 272 } 273 } 274 275 int posix_kill(posix_pid_t pid, int signo) 276 { 277 if (pid < 1) { 278 // TODO 279 errno = ENOTSUP; 280 return -1; 281 } 282 283 if (pid == task_get_id()) { 284 return posix_raise(signo); 285 } 286 287 if (pid > _TOP_SIGNAL) { 288 errno = EINVAL; 289 return -1; 290 } 291 292 switch (signo) { 293 case SIGKILL: 294 task_kill(pid); 295 break; 296 default: 297 /* Nothing else supported yet. */ 298 errno = ENOTSUP; 299 return -1; 300 } 301 302 return 0; 303 } 304 305 int posix_killpg(posix_pid_t pid, int sig) 306 { 307 assert(pid > 1); 308 return posix_kill(-pid, sig); 309 } 310 311 void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message) 312 { 313 assert(pinfo != NULL); 314 posix_psignal(pinfo->si_signo, message); 315 // TODO: print si_code 316 } 317 318 void posix_psignal(int signum, const char *message) 319 { 320 char *sigmsg = posix_strsignal(signum); 321 if (message == NULL || *message == '\0') { 322 fprintf(stderr, "%s\n", sigmsg); 323 } else { 324 fprintf(stderr, "%s: %s\n", message, sigmsg); 325 } 326 } 327 328 int posix_thread_sigmask(int how, const posix_sigset_t *restrict set, 329 posix_sigset_t *restrict oset) 330 { 331 fibril_mutex_lock(&_signal_mutex); 332 333 if (oset != NULL) { 334 *oset = _signal_mask; 335 } 336 if (set != NULL) { 337 switch (how) { 338 case SIG_BLOCK: 339 _signal_mask |= *set; 340 break; 341 case SIG_UNBLOCK: 342 _signal_mask &= ~*set; 343 break; 344 case SIG_SETMASK: 345 _signal_mask = *set; 346 break; 347 default: 348 fibril_mutex_unlock(&_signal_mutex); 349 return EINVAL; 350 } 351 } 352 353 // TODO: queued signal handling 354 355 fibril_mutex_unlock(&_signal_mutex); 356 357 return 0; 68 358 } 69 359 … … 71 361 posix_sigset_t *restrict oset) 72 362 { 73 // TODO 74 not_implemented(); 363 int result = posix_thread_sigmask(how, set, oset); 364 if (result != 0) { 365 errno = result; 366 return -1; 367 } 368 return 0; 75 369 } 76 370
Note:
See TracChangeset
for help on using the changeset viewer.