Author: bonefish Date: 2011-05-18 18:09:42 +0200 (Wed, 18 May 2011) New Revision: 41568 Changeset: https://dev.haiku-os.org/changeset/41568 Ticket: https://dev.haiku-os.org/ticket/2695 Modified: haiku/branches/developer/bonefish/signals/headers/posix/signal.h haiku/branches/developer/bonefish/signals/src/system/kernel/arch/x86/arch_thread.cpp Log: Applied partial patch by Andreas Faerber (ticket #2695) with some style changes: * <signal.h>: Added/uncommented/extended the structures needed for SA_SIGINFO support. * arch_setup_signal_frame(): Added (partial) support for setting up the signal frame for SA_SIGINFO style handlers. Modified: haiku/branches/developer/bonefish/signals/headers/posix/signal.h =================================================================== --- haiku/branches/developer/bonefish/signals/headers/posix/signal.h 2011-05-18 15:21:47 UTC (rev 41567) +++ haiku/branches/developer/bonefish/signals/headers/posix/signal.h 2011-05-18 16:09:42 UTC (rev 41568) @@ -1,5 +1,5 @@ /* - * Copyright 2002-2010 Haiku Inc. All Rights Reserved. + * Copyright 2002-2011 Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. */ #ifndef _SIGNAL_H_ @@ -25,21 +25,23 @@ #define SIG_ERR ((sighandler_t)-1) /* an error occurred during signal processing */ #define SIG_HOLD ((sighandler_t)3) /* the signal was hold */ -/* TODO: Support this structure, or more precisely the SA_SIGINFO flag. To do - * this properly we need real-time signal support. Both are commented out for - * the time being to not make "configure" scripts think we do support them. */ -#if 0 +union sigval { + int sival_int; + void *sival_ptr; +}; + typedef struct { - int si_signo; /* signal number */ - int si_code; /* signal code */ - int si_errno; /* if non zero, an error number associated with this signal */ - pid_t si_pid; /* sending process ID */ - uid_t si_uid; /* real user ID of sending process */ - void *si_addr; /* address of faulting instruction */ - int si_status; /* exit value or signal */ - long si_band; /* band event for SIGPOLL */ + int si_signo; /* signal number */ + int si_code; /* signal code */ + int si_errno; /* if non zero, an error number associated with + this signal */ + pid_t si_pid; /* sending process ID */ + uid_t si_uid; /* real user ID of sending process */ + void *si_addr; /* address of faulting instruction */ + int si_status; /* exit value or signal */ + long si_band; /* band event for SIGPOLL */ + union sigval si_value; /* signal value */ } siginfo_t; -#endif /* 0 */ /* * structure used by sigaction() @@ -48,7 +50,10 @@ * See the documentation for more info on this. */ struct sigaction { - sighandler_t sa_handler; + union { + sighandler_t sa_handler; + void (*sa_sigaction)(int, siginfo_t *, void *); + }; sigset_t sa_mask; int sa_flags; void *sa_userdata; /* will be passed to the signal handler */ @@ -61,7 +66,7 @@ #define SA_NODEFER 0x08 #define SA_RESTART 0x10 #define SA_ONSTACK 0x20 -/* #define SA_SIGINFO 0x40 */ +#define SA_SIGINFO 0x40 #define SA_NOMASK SA_NODEFER #define SA_STACK SA_ONSTACK #define SA_ONESHOT SA_RESETHAND @@ -251,5 +256,14 @@ /* include architecture specific definitions */ #include __HAIKU_ARCH_HEADER(signal.h) +typedef struct vregs mcontext_t; +typedef struct ucontext_t { + struct ucontext_t *uc_link; + sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; +} ucontext_t; + + #endif /* _SIGNAL_H_ */ Modified: haiku/branches/developer/bonefish/signals/src/system/kernel/arch/x86/arch_thread.cpp =================================================================== --- haiku/branches/developer/bonefish/signals/src/system/kernel/arch/x86/arch_thread.cpp 2011-05-18 15:21:47 UTC (rev 41567) +++ haiku/branches/developer/bonefish/signals/src/system/kernel/arch/x86/arch_thread.cpp 2011-05-18 16:09:42 UTC (rev 41568) @@ -485,7 +485,10 @@ uint32 *signalCode; uint32 *userRegs; - struct vregs regs; + uint32 *userSiginfo = NULL; + uint32 *userContext = NULL; + siginfo_t siginfo; + ucontext_t ucontext; uint32 buffer[6]; status_t status; @@ -505,23 +508,43 @@ if (status < B_OK) return status; + if ((action->sa_flags & SA_SIGINFO) != 0) { + // store the signal info + memset(&siginfo, 0, sizeof(siginfo)); + siginfo.si_signo = signal->Number(); + // TODO: fill in other members + + userStack -= (sizeof(siginfo_t) + 3) / 4; + userSiginfo = userStack; + status = user_memcpy(userSiginfo, &siginfo, sizeof(siginfo)); + if (status < B_OK) + return status; + } + // store the saved regs onto the user stack - regs.eip = frame->eip; - regs.eflags = frame->flags; - regs.eax = frame->eax; - regs.ecx = frame->ecx; - regs.edx = frame->edx; - regs.ebp = frame->ebp; - regs.esp = frame->esp; - regs._reserved_1 = frame->user_esp; - regs._reserved_2[0] = frame->edi; - regs._reserved_2[1] = frame->esi; - regs._reserved_2[2] = frame->ebx; - i386_fnsave((void *)(®s.xregs)); + ucontext.uc_mcontext.eip = frame->eip; + ucontext.uc_mcontext.eflags = frame->flags; + ucontext.uc_mcontext.eax = frame->eax; + ucontext.uc_mcontext.ecx = frame->ecx; + ucontext.uc_mcontext.edx = frame->edx; + ucontext.uc_mcontext.ebp = frame->ebp; + ucontext.uc_mcontext.esp = frame->esp; + ucontext.uc_mcontext._reserved_1 = frame->user_esp; + ucontext.uc_mcontext._reserved_2[0] = frame->edi; + ucontext.uc_mcontext._reserved_2[1] = frame->esi; + ucontext.uc_mcontext._reserved_2[2] = frame->ebx; + i386_fnsave((void *)(&ucontext.uc_mcontext.xregs)); - userStack -= (sizeof(struct vregs) + 3) / 4; - userRegs = userStack; - status = user_memcpy(userRegs, ®s, sizeof(regs)); + if ((action->sa_flags & SA_SIGINFO) != 0) { + userStack -= (sizeof(ucontext_t) + 3) / 4; + userContext = userStack; + userRegs = userContext + offsetof(ucontext_t, uc_mcontext); + status = user_memcpy(userContext, &ucontext, sizeof(ucontext)); + } else { + userStack -= (sizeof(struct vregs) + 3) / 4; + userRegs = userStack; + status = user_memcpy(userRegs, &ucontext.uc_mcontext, sizeof(struct vregs)); + } if (status < B_OK) return status; @@ -538,8 +561,13 @@ // now set up the final part buffer[0] = (uint32)signalCode; // return address when sa_handler done buffer[1] = signal->Number(); // arguments to sa_handler - buffer[2] = (uint32)action->sa_userdata; - buffer[3] = (uint32)userRegs; + if ((action->sa_flags & SA_SIGINFO) != 0) { + buffer[2] = (uint32)userSiginfo; + buffer[3] = (uint32)userContext; + } else { + buffer[2] = (uint32)action->sa_userdata; + buffer[3] = (uint32)userRegs; + } buffer[4] = signalMask; // Old signal mask to restore buffer[5] = (uint32)userRegs; // Int frame + extra regs to restore @@ -551,7 +579,8 @@ return status; frame->user_esp = (uint32)userStack; - frame->eip = (uint32)action->sa_handler; + frame->eip = (action->sa_flags & SA_SIGINFO) != 0 + ? (uint32)action->sa_sigaction : (uint32)action->sa_handler; return B_OK; }