diff -r d8416f83885f headers/posix/signal.h
a
|
b
|
|
25 | 25 | #define SIG_ERR ((sighandler_t)-1) /* an error occurred during signal processing */ |
26 | 26 | #define SIG_HOLD ((sighandler_t)3) /* the signal was hold */ |
27 | 27 | |
28 | | /* TODO: Support this structure, or more precisely the SA_SIGINFO flag. To do |
29 | | * this properly we need real-time signal support. Both are commented out for |
30 | | * the time being to not make "configure" scripts think we do support them. */ |
31 | | #if 0 |
| 28 | union sigval { |
| 29 | int sival_int; |
| 30 | void *sival_ptr; |
| 31 | }; |
| 32 | |
32 | 33 | typedef struct { |
33 | 34 | int si_signo; /* signal number */ |
34 | 35 | int si_code; /* signal code */ |
… |
… |
|
38 | 39 | void *si_addr; /* address of faulting instruction */ |
39 | 40 | int si_status; /* exit value or signal */ |
40 | 41 | long si_band; /* band event for SIGPOLL */ |
| 42 | union sigval si_value; /* signal value */ |
41 | 43 | } siginfo_t; |
42 | | #endif /* 0 */ |
43 | 44 | |
44 | 45 | /* |
45 | 46 | * structure used by sigaction() |
… |
… |
|
48 | 49 | * See the documentation for more info on this. |
49 | 50 | */ |
50 | 51 | struct sigaction { |
51 | | sighandler_t sa_handler; |
| 52 | union { |
| 53 | sighandler_t sa_handler; |
| 54 | void (*sa_sigaction)(int, siginfo_t *, void *); |
| 55 | }; |
52 | 56 | sigset_t sa_mask; |
53 | 57 | int sa_flags; |
54 | 58 | void *sa_userdata; /* will be passed to the signal handler */ |
… |
… |
|
61 | 65 | #define SA_NODEFER 0x08 |
62 | 66 | #define SA_RESTART 0x10 |
63 | 67 | #define SA_ONSTACK 0x20 |
64 | | /* #define SA_SIGINFO 0x40 */ |
| 68 | #define SA_SIGINFO 0x40 |
65 | 69 | #define SA_NOMASK SA_NODEFER |
66 | 70 | #define SA_STACK SA_ONSTACK |
67 | 71 | #define SA_ONESHOT SA_RESETHAND |
… |
… |
|
251 | 255 | /* include architecture specific definitions */ |
252 | 256 | #include __HAIKU_ARCH_HEADER(signal.h) |
253 | 257 | |
| 258 | typedef struct vregs mcontext_t; |
| 259 | |
| 260 | typedef struct ucontext_t { |
| 261 | struct ucontext_t *uc_link; |
| 262 | sigset_t uc_sigmask; |
| 263 | stack_t uc_stack; |
| 264 | mcontext_t uc_mcontext; |
| 265 | } ucontext_t; |
| 266 | |
254 | 267 | |
255 | 268 | #endif /* _SIGNAL_H_ */ |
diff -r d8416f83885f headers/private/kernel/ksignal.h
a
|
b
|
|
34 | 34 | extern int sigaction_etc(thread_id threadID, int signal, |
35 | 35 | const struct sigaction *newAction, struct sigaction *oldAction); |
36 | 36 | |
| 37 | extern int send_signal_AF(pid_t threadID, const siginfo_t *info); |
| 38 | |
37 | 39 | extern status_t _user_send_signal(pid_t tid, uint sig); |
38 | 40 | extern status_t _user_sigprocmask(int how, const sigset_t *set, |
39 | 41 | sigset_t *oldSet); |
diff -r d8416f83885f headers/private/kernel/thread_types.h
a
|
b
|
|
231 | 231 | typedef bool (*page_fault_callback)(addr_t address, addr_t faultAddress, |
232 | 232 | bool isWrite); |
233 | 233 | |
| 234 | struct signal_entry { |
| 235 | struct list_link link; |
| 236 | siginfo_t info; |
| 237 | }; |
| 238 | |
234 | 239 | struct thread { |
235 | 240 | int32 flags; // summary of events relevant in interrupt |
236 | 241 | // handlers (signals pending, user debugging |
… |
… |
|
258 | 263 | size_t signal_stack_size; |
259 | 264 | bool signal_stack_enabled; |
260 | 265 | |
| 266 | struct list signal_queue; |
| 267 | |
261 | 268 | bool in_kernel; |
262 | 269 | bool was_yielded; |
263 | 270 | struct scheduler_thread_data* scheduler_data; |
diff -r d8416f83885f src/system/kernel/arch/x86/arch_thread.cpp
a
|
b
|
|
483 | 483 | } |
484 | 484 | |
485 | 485 | uint32 *signalCode; |
486 | | uint32 *userRegs; |
487 | | struct vregs regs; |
| 486 | uint32 *userRegs, *userSiginfo, *userContext; |
| 487 | siginfo_t siginfo; |
| 488 | ucontext_t ucontext; |
488 | 489 | uint32 buffer[6]; |
489 | 490 | status_t status; |
490 | 491 | |
… |
… |
|
504 | 505 | if (status < B_OK) |
505 | 506 | return status; |
506 | 507 | |
| 508 | if (action->sa_flags & SA_SIGINFO) { |
| 509 | // store the signal info |
| 510 | memset(&siginfo, 0, sizeof(siginfo)); |
| 511 | siginfo.si_signo = signal; |
| 512 | //TODO fill in other members |
| 513 | |
| 514 | userStack -= (sizeof(siginfo_t) + 3) / 4; |
| 515 | userSiginfo = userStack; |
| 516 | status = user_memcpy(userSiginfo, &siginfo, sizeof(siginfo)); |
| 517 | if (status < B_OK) |
| 518 | return status; |
| 519 | } |
| 520 | |
507 | 521 | // store the saved regs onto the user stack |
508 | | regs.eip = frame->eip; |
509 | | regs.eflags = frame->flags; |
510 | | regs.eax = frame->eax; |
511 | | regs.ecx = frame->ecx; |
512 | | regs.edx = frame->edx; |
513 | | regs.ebp = frame->ebp; |
514 | | regs.esp = frame->esp; |
515 | | regs._reserved_1 = frame->user_esp; |
516 | | regs._reserved_2[0] = frame->edi; |
517 | | regs._reserved_2[1] = frame->esi; |
518 | | regs._reserved_2[2] = frame->ebx; |
519 | | i386_fnsave((void *)(®s.xregs)); |
| 522 | ucontext.uc_mcontext.eip = frame->eip; |
| 523 | ucontext.uc_mcontext.eflags = frame->flags; |
| 524 | ucontext.uc_mcontext.eax = frame->eax; |
| 525 | ucontext.uc_mcontext.ecx = frame->ecx; |
| 526 | ucontext.uc_mcontext.edx = frame->edx; |
| 527 | ucontext.uc_mcontext.ebp = frame->ebp; |
| 528 | ucontext.uc_mcontext.esp = frame->esp; |
| 529 | ucontext.uc_mcontext._reserved_1 = frame->user_esp; |
| 530 | ucontext.uc_mcontext._reserved_2[0] = frame->edi; |
| 531 | ucontext.uc_mcontext._reserved_2[1] = frame->esi; |
| 532 | ucontext.uc_mcontext._reserved_2[2] = frame->ebx; |
| 533 | i386_fnsave((void *)(&ucontext.uc_mcontext.xregs)); |
520 | 534 | |
521 | | userStack -= (sizeof(struct vregs) + 3) / 4; |
522 | | userRegs = userStack; |
523 | | status = user_memcpy(userRegs, ®s, sizeof(regs)); |
| 535 | if (action->sa_flags & SA_SIGINFO) { |
| 536 | userStack -= (sizeof(ucontext_t) + 3) / 4; |
| 537 | userContext = userStack; |
| 538 | userRegs = userContext + offsetof(ucontext_t, uc_mcontext); |
| 539 | status = user_memcpy(userContext, &ucontext, sizeof(ucontext)); |
| 540 | } else { |
| 541 | userStack -= (sizeof(struct vregs) + 3) / 4; |
| 542 | userRegs = userStack; |
| 543 | status = user_memcpy(userRegs, &ucontext.uc_mcontext, sizeof(struct vregs)); |
| 544 | } |
524 | 545 | if (status < B_OK) |
525 | 546 | return status; |
526 | 547 | |
… |
… |
|
537 | 558 | // now set up the final part |
538 | 559 | buffer[0] = (uint32)signalCode; // return address when sa_handler done |
539 | 560 | buffer[1] = signal; // arguments to sa_handler |
540 | | buffer[2] = (uint32)action->sa_userdata; |
541 | | buffer[3] = (uint32)userRegs; |
| 561 | if (action->sa_flags & SA_SIGINFO) { |
| 562 | buffer[2] = (uint32)userSiginfo; |
| 563 | buffer[3] = (uint32)userContext; |
| 564 | } else { |
| 565 | buffer[2] = (uint32)action->sa_userdata; |
| 566 | buffer[3] = (uint32)userRegs; |
| 567 | } |
542 | 568 | |
543 | 569 | buffer[4] = signalMask; // Old signal mask to restore |
544 | 570 | buffer[5] = (uint32)userRegs; // Int frame + extra regs to restore |
… |
… |
|
550 | 576 | return status; |
551 | 577 | |
552 | 578 | frame->user_esp = (uint32)userStack; |
553 | | frame->eip = (uint32)action->sa_handler; |
| 579 | frame->eip = (action->sa_flags & SA_SIGINFO) ? (uint32)action->sa_sigaction : (uint32)action->sa_handler; |
554 | 580 | |
555 | 581 | return B_OK; |
556 | 582 | } |
diff -r d8416f83885f src/system/kernel/signal.cpp
a
|
b
|
|
61 | 61 | }; |
62 | 62 | |
63 | 63 | |
64 | | static status_t deliver_signal(struct thread *thread, uint signal, |
| 64 | static status_t deliver_signal(struct thread *thread, const siginfo_t *info, |
65 | 65 | uint32 flags); |
66 | 66 | |
67 | 67 | |
… |
… |
|
337 | 337 | |
338 | 338 | T(HandleSignals(signalMask)); |
339 | 339 | |
340 | | for (int32 i = 0; i < NSIG; i++) { |
| 340 | //for (int32 i = 0; i < NSIG; i++) { |
| 341 | siginfo_t *signalInfo = NULL; |
| 342 | while ((signalInfo = (siginfo_t *)list_get_next_item(&thread->signal_queue, NULL)) != NULL) { |
341 | 343 | bool debugSignal; |
342 | | int32 signal = i + 1; |
| 344 | //int32 signal = i + 1; |
| 345 | int32 signal = signalInfo->si_signo; |
343 | 346 | |
344 | 347 | if ((signalMask & SIGNAL_TO_MASK(signal)) == 0) |
345 | 348 | continue; |
346 | 349 | |
347 | 350 | // clear the signal that we will handle |
348 | | atomic_and(&thread->sig_pending, ~SIGNAL_TO_MASK(signal)); |
| 351 | //atomic_and(&thread->sig_pending, ~SIGNAL_TO_MASK(signal)); |
| 352 | list_remove_item(&thread->signal_queue, signalInfo); |
349 | 353 | |
350 | 354 | debugSignal = !(~atomic_get(&thread->team->debug_info.flags) |
351 | 355 | & (B_TEAM_DEBUG_SIGNALS | B_TEAM_DEBUG_DEBUGGER_INSTALLED)); |
… |
… |
|
359 | 363 | // handlers to work only when the respective thread is stopped. |
360 | 364 | // Then sigaction() could be used instead and we could get rid of |
361 | 365 | // sigaction_etc(). |
362 | | struct sigaction* handler = &thread->sig_action[i]; |
| 366 | //struct sigaction* handler = &thread->sig_action[i]; |
| 367 | ASSERT(signal <= NSIG); |
| 368 | struct sigaction* handler = &thread->sig_action[signal - 1]; |
363 | 369 | |
364 | 370 | TRACE(("Thread 0x%lx received signal %s\n", thread->id, sigstr[signal])); |
365 | 371 | |
366 | 372 | if (handler->sa_handler == SIG_IGN) { |
367 | 373 | // signal is to be ignored |
| 374 | free((uint8_t*)signalInfo - sizeof(list_link)); |
368 | 375 | // ToDo: apply zombie cleaning on SIGCHLD |
369 | 376 | |
370 | 377 | // notify the debugger |
… |
… |
|
373 | 380 | continue; |
374 | 381 | } else if (handler->sa_handler == SIG_DFL) { |
375 | 382 | // default signal behaviour |
| 383 | free((uint8_t*)signalInfo - sizeof(list_link)); |
376 | 384 | switch (signal) { |
377 | 385 | case SIGCHLD: |
378 | 386 | case SIGWINCH: |
… |
… |
|
424 | 432 | = thread->team->parent->main_thread; |
425 | 433 | struct sigaction& parentHandler |
426 | 434 | = parentThread->sig_action[SIGCHLD - 1]; |
427 | | if ((parentHandler.sa_flags & SA_NOCLDSTOP) == 0) |
428 | | deliver_signal(parentThread, SIGCHLD, 0); |
| 435 | if ((parentHandler.sa_flags & SA_NOCLDSTOP) == 0) { |
| 436 | siginfo_t info; |
| 437 | memset(&info, 0, sizeof(siginfo_t)); |
| 438 | info.si_signo = SIGCHLD; |
| 439 | deliver_signal(parentThread, &info, 0); |
| 440 | } |
429 | 441 | } |
430 | 442 | |
431 | 443 | return true; |
… |
… |
|
472 | 484 | // User defined signal handler |
473 | 485 | |
474 | 486 | // notify the debugger |
475 | | if (debugSignal && !notify_debugger(thread, signal, handler, false)) |
| 487 | if (debugSignal && !notify_debugger(thread, signal, handler, false)) { |
| 488 | free((uint8_t*)signalInfo - sizeof(list_link)); |
476 | 489 | continue; |
| 490 | } |
477 | 491 | |
478 | 492 | if (!restart || (handler->sa_flags & SA_RESTART) == 0) |
479 | 493 | atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); |
… |
… |
|
484 | 498 | arch_setup_signal_frame(thread, handler, signal, |
485 | 499 | atomic_get(&thread->sig_block_mask)); |
486 | 500 | |
487 | | if (handler->sa_flags & SA_ONESHOT) |
| 501 | if (handler->sa_flags & SA_ONESHOT) { |
488 | 502 | handler->sa_handler = SIG_DFL; |
| 503 | atomic_and(&handler->sa_flags, ~(SA_SIGINFO | SA_ONESHOT)); |
| 504 | } |
489 | 505 | if ((handler->sa_flags & SA_NOMASK) == 0) { |
490 | 506 | // Update the block mask while the signal handler is running - it |
491 | 507 | // will be automatically restored when the signal frame is left. |
492 | 508 | atomic_or(&thread->sig_block_mask, |
493 | 509 | (handler->sa_mask | SIGNAL_TO_MASK(signal)) & BLOCKABLE_SIGNALS); |
494 | 510 | } |
| 511 | free((uint8_t*)signalInfo - sizeof(list_link)); |
495 | 512 | |
496 | 513 | update_current_thread_signals_flag(); |
497 | 514 | |
… |
… |
|
531 | 548 | thread lock held. |
532 | 549 | */ |
533 | 550 | static status_t |
534 | | deliver_signal(struct thread *thread, uint signal, uint32 flags) |
| 551 | deliver_signal(struct thread *thread, const siginfo_t *signalInfo, uint32 flags) |
535 | 552 | { |
| 553 | ASSERT(signalInfo != NULL); |
| 554 | uint signal = signalInfo->si_signo; |
536 | 555 | if (flags & B_CHECK_PERMISSION) { |
537 | 556 | // ToDo: introduce euid & uid fields to the team and check permission |
538 | 557 | } |
… |
… |
|
547 | 566 | return B_OK; |
548 | 567 | } |
549 | 568 | |
550 | | atomic_or(&thread->sig_pending, SIGNAL_TO_MASK(signal)); |
| 569 | //atomic_or(&thread->sig_pending, SIGNAL_TO_MASK(signal)); |
| 570 | struct signal_entry *signalEntry; |
| 571 | signalEntry = (struct signal_entry *)malloc(sizeof(signal_entry)); |
| 572 | if (signalEntry == NULL) |
| 573 | return B_OK; |
| 574 | memcpy(&signalEntry->info, signalInfo, sizeof(siginfo_t)); |
| 575 | list_add_link_to_tail(&thread->signal_queue, signalEntry); |
551 | 576 | |
552 | 577 | switch (signal) { |
553 | 578 | case SIGKILL: |
554 | 579 | { |
555 | 580 | // Forward KILLTHR to the main thread of the team |
556 | 581 | struct thread *mainThread = thread->team->main_thread; |
557 | | atomic_or(&mainThread->sig_pending, SIGNAL_TO_MASK(SIGKILLTHR)); |
| 582 | //atomic_or(&mainThread->sig_pending, SIGNAL_TO_MASK(SIGKILLTHR)); |
| 583 | signalEntry = (struct signal_entry *)malloc(sizeof(signal_entry)); |
| 584 | if (signalEntry == NULL) |
| 585 | return B_OK; |
| 586 | signalEntry->info.si_signo = SIGKILLTHR; |
| 587 | list_add_link_to_tail(&mainThread->signal_queue, signalEntry); |
558 | 588 | |
559 | 589 | // Wake up main thread |
560 | 590 | if (mainThread->state == B_THREAD_SUSPENDED) |
… |
… |
|
582 | 612 | if ((flags & SIGNAL_FLAG_DONT_RESTART_SYSCALL) != 0) |
583 | 613 | atomic_or(&thread->flags, THREAD_FLAGS_DONT_RESTART_SYSCALL); |
584 | 614 | |
585 | | atomic_and(&thread->sig_pending, ~STOP_SIGNALS); |
| 615 | //atomic_and(&thread->sig_pending, ~STOP_SIGNALS); |
586 | 616 | // remove any pending stop signals |
| 617 | { |
| 618 | siginfo_t *sigInfo = NULL; |
| 619 | while ((sigInfo = (siginfo_t *)list_get_next_item(&thread->signal_queue, sigInfo)) != NULL) { |
| 620 | switch (sigInfo->si_signo) { |
| 621 | case SIGSTOP: |
| 622 | case SIGTSTP: |
| 623 | case SIGTTIN: |
| 624 | case SIGTTOU: |
| 625 | list_remove_item(&thread->signal_queue, sigInfo); |
| 626 | free((uint8_t*)sigInfo - sizeof(list_link)); |
| 627 | sigInfo = NULL; // restart search |
| 628 | break; |
| 629 | } |
| 630 | } |
| 631 | } |
587 | 632 | break; |
588 | 633 | |
589 | 634 | default: |
… |
… |
|
601 | 646 | } |
602 | 647 | |
603 | 648 | |
604 | | int |
605 | | send_signal_etc(pid_t id, uint signal, uint32 flags) |
| 649 | static int |
| 650 | send_signal_etc_AF(pid_t id, const siginfo_t* info, uint32 flags) |
606 | 651 | { |
| 652 | ASSERT(info != NULL); |
| 653 | uint signal = info->si_signo; |
607 | 654 | status_t status = B_BAD_THREAD_ID; |
608 | 655 | struct thread *thread; |
609 | 656 | cpu_status state = 0; |
… |
… |
|
623 | 670 | |
624 | 671 | thread = thread_get_thread_struct_locked(id); |
625 | 672 | if (thread != NULL) |
626 | | status = deliver_signal(thread, signal, flags); |
| 673 | status = deliver_signal(thread, info, flags); |
627 | 674 | } else { |
628 | 675 | // send a signal to the specified process group |
629 | 676 | // (the absolute value of the id) |
… |
… |
|
656 | 703 | if (thread != NULL) { |
657 | 704 | // we don't stop because of an error sending the signal; we |
658 | 705 | // rather want to send as much signals as possible |
659 | | status = deliver_signal(thread, signal, flags); |
| 706 | status = deliver_signal(thread, info, flags); |
660 | 707 | } |
661 | 708 | |
662 | 709 | RELEASE_THREAD_LOCK(); |
… |
… |
|
682 | 729 | |
683 | 730 | |
684 | 731 | int |
| 732 | send_signal_etc(pid_t id, uint signal, uint32 flags) |
| 733 | { |
| 734 | siginfo_t info; |
| 735 | memset(&info, 0, sizeof(siginfo_t)); |
| 736 | info.si_signo = signal; |
| 737 | return send_signal_etc_AF(id, &info, flags); |
| 738 | } |
| 739 | |
| 740 | |
| 741 | int |
| 742 | send_signal_AF(pid_t threadID, const siginfo_t* info) |
| 743 | { |
| 744 | return send_signal_etc_AF(threadID, info, 0); |
| 745 | } |
| 746 | |
| 747 | int |
685 | 748 | send_signal(pid_t threadID, uint signal) |
686 | 749 | { |
687 | 750 | // The BeBook states that this function wouldn't be exported |
diff -r d8416f83885f src/system/kernel/thread.cpp
a
|
b
|
|
200 | 200 | thread->signal_stack_base = 0; |
201 | 201 | thread->signal_stack_size = 0; |
202 | 202 | thread->signal_stack_enabled = false; |
| 203 | list_init_etc(&thread->signal_queue, offsetof(struct signal_entry, info)); |
203 | 204 | } |
204 | 205 | |
205 | 206 | |
diff -r d8416f83885f src/system/kernel/vm/vm.cpp
a
|
b
|
|
3876 | 3876 | // If the thread has a signal handler for SIGSEGV, we simply |
3877 | 3877 | // send it the signal. Otherwise we notify the user debugger |
3878 | 3878 | // first. |
| 3879 | siginfo_t info; |
| 3880 | memset(&info, 0, sizeof(siginfo_t)); |
| 3881 | info.si_signo = SIGSEGV; |
| 3882 | info.si_addr = (void *)(unsigned long)faultAddress; |
3879 | 3883 | struct sigaction action; |
3880 | 3884 | if (sigaction(SIGSEGV, NULL, &action) == 0 |
3881 | 3885 | && action.sa_handler != SIG_DFL |
3882 | 3886 | && action.sa_handler != SIG_IGN) { |
3883 | | send_signal(thread->id, SIGSEGV); |
| 3887 | send_signal_AF(thread->id, &info); |
3884 | 3888 | } else if (user_debug_exception_occurred(B_SEGMENT_VIOLATION, |
3885 | 3889 | SIGSEGV)) { |
3886 | 3890 | send_signal(thread->id, SIGSEGV); |