Ticket #2695: siginfo-2010-04-05.diff

File siginfo-2010-04-05.diff, 14.6 KB (added by andreasf, 14 years ago)

draft patch

  • headers/posix/signal.h

    diff -r d8416f83885f headers/posix/signal.h
    a b  
    2525#define SIG_ERR     ((sighandler_t)-1)  /* an error occurred during signal processing */
    2626#define SIG_HOLD    ((sighandler_t)3)   /* the signal was hold */
    2727
    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
     28union sigval {
     29    int     sival_int;
     30    void    *sival_ptr;
     31};
     32
    3233typedef struct {
    3334    int     si_signo;   /* signal number */
    3435    int     si_code;    /* signal code */
     
    3839    void    *si_addr;   /* address of faulting instruction */
    3940    int     si_status;  /* exit value or signal */
    4041    long    si_band;    /* band event for SIGPOLL */
     42    union sigval    si_value; /* signal value */
    4143} siginfo_t;
    42 #endif  /* 0 */
    4344
    4445/*
    4546 * structure used by sigaction()
     
    4849 * See the documentation for more info on this.
    4950 */
    5051struct sigaction {
    51     sighandler_t sa_handler;
     52    union {
     53        sighandler_t    sa_handler;
     54        void            (*sa_sigaction)(int, siginfo_t *, void *);
     55    };
    5256    sigset_t    sa_mask;
    5357    int         sa_flags;
    5458    void        *sa_userdata;  /* will be passed to the signal handler */
     
    6165#define SA_NODEFER      0x08
    6266#define SA_RESTART      0x10
    6367#define SA_ONSTACK      0x20
    64 /* #define SA_SIGINFO       0x40 */
     68#define SA_SIGINFO      0x40
    6569#define SA_NOMASK       SA_NODEFER
    6670#define SA_STACK        SA_ONSTACK
    6771#define SA_ONESHOT      SA_RESETHAND
     
    251255/* include architecture specific definitions */
    252256#include __HAIKU_ARCH_HEADER(signal.h)
    253257
     258typedef struct vregs mcontext_t;
     259
     260typedef 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
    254267
    255268#endif /* _SIGNAL_H_ */
  • headers/private/kernel/ksignal.h

    diff -r d8416f83885f headers/private/kernel/ksignal.h
    a b  
    3434extern int sigaction_etc(thread_id threadID, int signal,
    3535    const struct sigaction *newAction, struct sigaction *oldAction);
    3636
     37extern int send_signal_AF(pid_t threadID, const siginfo_t *info);
     38
    3739extern status_t _user_send_signal(pid_t tid, uint sig);
    3840extern status_t _user_sigprocmask(int how, const sigset_t *set,
    3941    sigset_t *oldSet);
  • headers/private/kernel/thread_types.h

    diff -r d8416f83885f headers/private/kernel/thread_types.h
    a b  
    231231typedef bool (*page_fault_callback)(addr_t address, addr_t faultAddress,
    232232    bool isWrite);
    233233
     234struct signal_entry {
     235    struct list_link    link;
     236    siginfo_t           info;
     237};
     238
    234239struct thread {
    235240    int32           flags;          // summary of events relevant in interrupt
    236241                                    // handlers (signals pending, user debugging
     
    258263    size_t          signal_stack_size;
    259264    bool            signal_stack_enabled;
    260265
     266    struct list     signal_queue;
     267
    261268    bool            in_kernel;
    262269    bool            was_yielded;
    263270    struct scheduler_thread_data* scheduler_data;
  • src/system/kernel/arch/x86/arch_thread.cpp

    diff -r d8416f83885f src/system/kernel/arch/x86/arch_thread.cpp
    a b  
    483483    }
    484484
    485485    uint32 *signalCode;
    486     uint32 *userRegs;
    487     struct vregs regs;
     486    uint32 *userRegs, *userSiginfo, *userContext;
     487    siginfo_t siginfo;
     488    ucontext_t ucontext;
    488489    uint32 buffer[6];
    489490    status_t status;
    490491
     
    504505    if (status < B_OK)
    505506        return status;
    506507
     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
    507521    // 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 *)(&regs.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));
    520534
    521     userStack -= (sizeof(struct vregs) + 3) / 4;
    522     userRegs = userStack;
    523     status = user_memcpy(userRegs, &regs, 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    }
    524545    if (status < B_OK)
    525546        return status;
    526547
     
    537558    // now set up the final part
    538559    buffer[0] = (uint32)signalCode; // return address when sa_handler done
    539560    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    }
    542568
    543569    buffer[4] = signalMask;         // Old signal mask to restore
    544570    buffer[5] = (uint32)userRegs;   // Int frame + extra regs to restore
     
    550576        return status;
    551577
    552578    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;
    554580
    555581    return B_OK;
    556582}
  • src/system/kernel/signal.cpp

    diff -r d8416f83885f src/system/kernel/signal.cpp
    a b  
    6161};
    6262
    6363
    64 static status_t deliver_signal(struct thread *thread, uint signal,
     64static status_t deliver_signal(struct thread *thread, const siginfo_t *info,
    6565    uint32 flags);
    6666
    6767
     
    337337
    338338    T(HandleSignals(signalMask));
    339339
    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) {
    341343        bool debugSignal;
    342         int32 signal = i + 1;
     344        //int32 signal = i + 1;
     345        int32 signal = signalInfo->si_signo;
    343346
    344347        if ((signalMask & SIGNAL_TO_MASK(signal)) == 0)
    345348            continue;
    346349
    347350        // 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);
    349353
    350354        debugSignal = !(~atomic_get(&thread->team->debug_info.flags)
    351355                & (B_TEAM_DEBUG_SIGNALS | B_TEAM_DEBUG_DEBUGGER_INSTALLED));
     
    359363        //      handlers to work only when the respective thread is stopped.
    360364        //      Then sigaction() could be used instead and we could get rid of
    361365        //      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];
    363369
    364370        TRACE(("Thread 0x%lx received signal %s\n", thread->id, sigstr[signal]));
    365371
    366372        if (handler->sa_handler == SIG_IGN) {
    367373            // signal is to be ignored
     374            free((uint8_t*)signalInfo - sizeof(list_link));
    368375            // ToDo: apply zombie cleaning on SIGCHLD
    369376
    370377            // notify the debugger
     
    373380            continue;
    374381        } else if (handler->sa_handler == SIG_DFL) {
    375382            // default signal behaviour
     383            free((uint8_t*)signalInfo - sizeof(list_link));
    376384            switch (signal) {
    377385                case SIGCHLD:
    378386                case SIGWINCH:
     
    424432                            = thread->team->parent->main_thread;
    425433                        struct sigaction& parentHandler
    426434                            = 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                        }
    429441                    }
    430442
    431443                    return true;
     
    472484        // User defined signal handler
    473485
    474486        // 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));
    476489            continue;
     490        }
    477491
    478492        if (!restart || (handler->sa_flags & SA_RESTART) == 0)
    479493            atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
     
    484498        arch_setup_signal_frame(thread, handler, signal,
    485499            atomic_get(&thread->sig_block_mask));
    486500
    487         if (handler->sa_flags & SA_ONESHOT)
     501        if (handler->sa_flags & SA_ONESHOT) {
    488502            handler->sa_handler = SIG_DFL;
     503            atomic_and(&handler->sa_flags, ~(SA_SIGINFO | SA_ONESHOT));
     504        }
    489505        if ((handler->sa_flags & SA_NOMASK) == 0) {
    490506            // Update the block mask while the signal handler is running - it
    491507            // will be automatically restored when the signal frame is left.
    492508            atomic_or(&thread->sig_block_mask,
    493509                (handler->sa_mask | SIGNAL_TO_MASK(signal)) & BLOCKABLE_SIGNALS);
    494510        }
     511        free((uint8_t*)signalInfo - sizeof(list_link));
    495512
    496513        update_current_thread_signals_flag();
    497514
     
    531548    thread lock held.
    532549*/
    533550static status_t
    534 deliver_signal(struct thread *thread, uint signal, uint32 flags)
     551deliver_signal(struct thread *thread, const siginfo_t *signalInfo, uint32 flags)
    535552{
     553    ASSERT(signalInfo != NULL);
     554    uint signal = signalInfo->si_signo;
    536555    if (flags & B_CHECK_PERMISSION) {
    537556        // ToDo: introduce euid & uid fields to the team and check permission
    538557    }
     
    547566        return B_OK;
    548567    }
    549568
    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);
    551576
    552577    switch (signal) {
    553578        case SIGKILL:
    554579        {
    555580            // Forward KILLTHR to the main thread of the team
    556581            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);
    558588
    559589            // Wake up main thread
    560590            if (mainThread->state == B_THREAD_SUSPENDED)
     
    582612            if ((flags & SIGNAL_FLAG_DONT_RESTART_SYSCALL) != 0)
    583613                atomic_or(&thread->flags, THREAD_FLAGS_DONT_RESTART_SYSCALL);
    584614
    585             atomic_and(&thread->sig_pending, ~STOP_SIGNALS);
     615            //atomic_and(&thread->sig_pending, ~STOP_SIGNALS);
    586616                // 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            }
    587632            break;
    588633
    589634        default:
     
    601646}
    602647
    603648
    604 int
    605 send_signal_etc(pid_t id, uint signal, uint32 flags)
     649static int
     650send_signal_etc_AF(pid_t id, const siginfo_t* info, uint32 flags)
    606651{
     652    ASSERT(info != NULL);
     653    uint signal = info->si_signo;
    607654    status_t status = B_BAD_THREAD_ID;
    608655    struct thread *thread;
    609656    cpu_status state = 0;
     
    623670
    624671        thread = thread_get_thread_struct_locked(id);
    625672        if (thread != NULL)
    626             status = deliver_signal(thread, signal, flags);
     673            status = deliver_signal(thread, info, flags);
    627674    } else {
    628675        // send a signal to the specified process group
    629676        // (the absolute value of the id)
     
    656703                if (thread != NULL) {
    657704                    // we don't stop because of an error sending the signal; we
    658705                    // rather want to send as much signals as possible
    659                     status = deliver_signal(thread, signal, flags);
     706                    status = deliver_signal(thread, info, flags);
    660707                }
    661708
    662709                RELEASE_THREAD_LOCK();
     
    682729
    683730
    684731int
     732send_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
     741int
     742send_signal_AF(pid_t threadID, const siginfo_t* info)
     743{
     744    return send_signal_etc_AF(threadID, info, 0);
     745}
     746
     747int
    685748send_signal(pid_t threadID, uint signal)
    686749{
    687750    // The BeBook states that this function wouldn't be exported
  • src/system/kernel/thread.cpp

    diff -r d8416f83885f src/system/kernel/thread.cpp
    a b  
    200200    thread->signal_stack_base = 0;
    201201    thread->signal_stack_size = 0;
    202202    thread->signal_stack_enabled = false;
     203    list_init_etc(&thread->signal_queue, offsetof(struct signal_entry, info));
    203204}
    204205
    205206
  • src/system/kernel/vm/vm.cpp

    diff -r d8416f83885f src/system/kernel/vm/vm.cpp
    a b  
    38763876                // If the thread has a signal handler for SIGSEGV, we simply
    38773877                // send it the signal. Otherwise we notify the user debugger
    38783878                // 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;
    38793883                struct sigaction action;
    38803884                if (sigaction(SIGSEGV, NULL, &action) == 0
    38813885                    && action.sa_handler != SIG_DFL
    38823886                    && action.sa_handler != SIG_IGN) {
    3883                     send_signal(thread->id, SIGSEGV);
     3887                    send_signal_AF(thread->id, &info);
    38843888                } else if (user_debug_exception_occurred(B_SEGMENT_VIOLATION,
    38853889                        SIGSEGV)) {
    38863890                    send_signal(thread->id, SIGSEGV);