diff -r d8416f83885f headers/posix/signal.h
--- a/headers/posix/signal.h	Mon Apr 05 13:10:28 2010 +0000
+++ b/headers/posix/signal.h	Tue Apr 06 02:52:34 2010 +0200
@@ -25,10 +25,11 @@
 #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 */
@@ -38,8 +39,8 @@
 	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 +49,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 +65,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 +255,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_ */
diff -r d8416f83885f headers/private/kernel/ksignal.h
--- a/headers/private/kernel/ksignal.h	Mon Apr 05 13:10:28 2010 +0000
+++ b/headers/private/kernel/ksignal.h	Tue Apr 06 02:52:34 2010 +0200
@@ -34,6 +34,8 @@
 extern int sigaction_etc(thread_id threadID, int signal,
 	const struct sigaction *newAction, struct sigaction *oldAction);
 
+extern int send_signal_AF(pid_t threadID, const siginfo_t *info);
+
 extern status_t _user_send_signal(pid_t tid, uint sig);
 extern status_t _user_sigprocmask(int how, const sigset_t *set,
 	sigset_t *oldSet);
diff -r d8416f83885f headers/private/kernel/thread_types.h
--- a/headers/private/kernel/thread_types.h	Mon Apr 05 13:10:28 2010 +0000
+++ b/headers/private/kernel/thread_types.h	Tue Apr 06 02:52:34 2010 +0200
@@ -231,6 +231,11 @@
 typedef bool (*page_fault_callback)(addr_t address, addr_t faultAddress,
 	bool isWrite);
 
+struct signal_entry {
+	struct list_link	link;
+	siginfo_t			info;
+};
+
 struct thread {
 	int32			flags;			// summary of events relevant in interrupt
 									// handlers (signals pending, user debugging
@@ -258,6 +263,8 @@
 	size_t			signal_stack_size;
 	bool			signal_stack_enabled;
 
+	struct list		signal_queue;
+
 	bool			in_kernel;
 	bool			was_yielded;
 	struct scheduler_thread_data* scheduler_data;
diff -r d8416f83885f src/system/kernel/arch/x86/arch_thread.cpp
--- a/src/system/kernel/arch/x86/arch_thread.cpp	Mon Apr 05 13:10:28 2010 +0000
+++ b/src/system/kernel/arch/x86/arch_thread.cpp	Tue Apr 06 02:52:34 2010 +0200
@@ -483,8 +483,9 @@
 	}
 
 	uint32 *signalCode;
-	uint32 *userRegs;
-	struct vregs regs;
+	uint32 *userRegs, *userSiginfo, *userContext;
+	siginfo_t siginfo;
+	ucontext_t ucontext;
 	uint32 buffer[6];
 	status_t status;
 
@@ -504,23 +505,43 @@
 	if (status < B_OK)
 		return status;
 
+	if (action->sa_flags & SA_SIGINFO) {
+		// store the signal info
+		memset(&siginfo, 0, sizeof(siginfo));
+		siginfo.si_signo = signal;
+		//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 *)(&regs.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, &regs, sizeof(regs));
+	if (action->sa_flags & SA_SIGINFO) {
+		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;
 
@@ -537,8 +558,13 @@
 	// now set up the final part
 	buffer[0] = (uint32)signalCode;	// return address when sa_handler done
 	buffer[1] = signal;				// arguments to sa_handler
-	buffer[2] = (uint32)action->sa_userdata;
-	buffer[3] = (uint32)userRegs;
+	if (action->sa_flags & SA_SIGINFO) {
+		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
@@ -550,7 +576,7 @@
 		return status;
 
 	frame->user_esp = (uint32)userStack;
-	frame->eip = (uint32)action->sa_handler;
+	frame->eip = (action->sa_flags & SA_SIGINFO) ? (uint32)action->sa_sigaction : (uint32)action->sa_handler;
 
 	return B_OK;
 }
diff -r d8416f83885f src/system/kernel/signal.cpp
--- a/src/system/kernel/signal.cpp	Mon Apr 05 13:10:28 2010 +0000
+++ b/src/system/kernel/signal.cpp	Tue Apr 06 02:52:34 2010 +0200
@@ -61,7 +61,7 @@
 };
 
 
-static status_t deliver_signal(struct thread *thread, uint signal,
+static status_t deliver_signal(struct thread *thread, const siginfo_t *info,
 	uint32 flags);
 
 
@@ -337,15 +337,19 @@
 
 	T(HandleSignals(signalMask));
 
-	for (int32 i = 0; i < NSIG; i++) {
+	//for (int32 i = 0; i < NSIG; i++) {
+	siginfo_t *signalInfo = NULL;
+	while ((signalInfo = (siginfo_t *)list_get_next_item(&thread->signal_queue, NULL)) != NULL) {
 		bool debugSignal;
-		int32 signal = i + 1;
+		//int32 signal = i + 1;
+		int32 signal = signalInfo->si_signo;
 
 		if ((signalMask & SIGNAL_TO_MASK(signal)) == 0)
 			continue;
 
 		// clear the signal that we will handle
-		atomic_and(&thread->sig_pending, ~SIGNAL_TO_MASK(signal));
+		//atomic_and(&thread->sig_pending, ~SIGNAL_TO_MASK(signal));
+		list_remove_item(&thread->signal_queue, signalInfo);
 
 		debugSignal = !(~atomic_get(&thread->team->debug_info.flags)
 				& (B_TEAM_DEBUG_SIGNALS | B_TEAM_DEBUG_DEBUGGER_INSTALLED));
@@ -359,12 +363,15 @@
 		//		handlers to work only when the respective thread is stopped.
 		//		Then sigaction() could be used instead and we could get rid of
 		//		sigaction_etc().
-		struct sigaction* handler = &thread->sig_action[i];
+		//struct sigaction* handler = &thread->sig_action[i];
+		ASSERT(signal <= NSIG);
+		struct sigaction* handler = &thread->sig_action[signal - 1];
 
 		TRACE(("Thread 0x%lx received signal %s\n", thread->id, sigstr[signal]));
 
 		if (handler->sa_handler == SIG_IGN) {
 			// signal is to be ignored
+			free((uint8_t*)signalInfo - sizeof(list_link));
 			// ToDo: apply zombie cleaning on SIGCHLD
 
 			// notify the debugger
@@ -373,6 +380,7 @@
 			continue;
 		} else if (handler->sa_handler == SIG_DFL) {
 			// default signal behaviour
+			free((uint8_t*)signalInfo - sizeof(list_link));
 			switch (signal) {
 				case SIGCHLD:
 				case SIGWINCH:
@@ -424,8 +432,12 @@
 							= thread->team->parent->main_thread;
 						struct sigaction& parentHandler
 							= parentThread->sig_action[SIGCHLD - 1];
-						if ((parentHandler.sa_flags & SA_NOCLDSTOP) == 0)
-							deliver_signal(parentThread, SIGCHLD, 0);
+						if ((parentHandler.sa_flags & SA_NOCLDSTOP) == 0) {
+							siginfo_t info;
+							memset(&info, 0, sizeof(siginfo_t));
+							info.si_signo = SIGCHLD;
+							deliver_signal(parentThread, &info, 0);
+						}
 					}
 
 					return true;
@@ -472,8 +484,10 @@
 		// User defined signal handler
 
 		// notify the debugger
-		if (debugSignal && !notify_debugger(thread, signal, handler, false))
+		if (debugSignal && !notify_debugger(thread, signal, handler, false)) {
+			free((uint8_t*)signalInfo - sizeof(list_link));
 			continue;
+		}
 
 		if (!restart || (handler->sa_flags & SA_RESTART) == 0)
 			atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
@@ -484,14 +498,17 @@
 		arch_setup_signal_frame(thread, handler, signal,
 			atomic_get(&thread->sig_block_mask));
 
-		if (handler->sa_flags & SA_ONESHOT)
+		if (handler->sa_flags & SA_ONESHOT) {
 			handler->sa_handler = SIG_DFL;
+			atomic_and(&handler->sa_flags, ~(SA_SIGINFO | SA_ONESHOT));
+		}
 		if ((handler->sa_flags & SA_NOMASK) == 0) {
 			// Update the block mask while the signal handler is running - it
 			// will be automatically restored when the signal frame is left.
 			atomic_or(&thread->sig_block_mask,
 				(handler->sa_mask | SIGNAL_TO_MASK(signal)) & BLOCKABLE_SIGNALS);
 		}
+		free((uint8_t*)signalInfo - sizeof(list_link));
 
 		update_current_thread_signals_flag();
 
@@ -531,8 +548,10 @@
 	thread lock held.
 */
 static status_t
-deliver_signal(struct thread *thread, uint signal, uint32 flags)
+deliver_signal(struct thread *thread, const siginfo_t *signalInfo, uint32 flags)
 {
+	ASSERT(signalInfo != NULL);
+	uint signal = signalInfo->si_signo;
 	if (flags & B_CHECK_PERMISSION) {
 		// ToDo: introduce euid & uid fields to the team and check permission
 	}
@@ -547,14 +566,25 @@
 		return B_OK;
 	}
 
-	atomic_or(&thread->sig_pending, SIGNAL_TO_MASK(signal));
+	//atomic_or(&thread->sig_pending, SIGNAL_TO_MASK(signal));
+	struct signal_entry *signalEntry;
+	signalEntry = (struct signal_entry *)malloc(sizeof(signal_entry));
+	if (signalEntry == NULL)
+		return B_OK;
+	memcpy(&signalEntry->info, signalInfo, sizeof(siginfo_t));
+	list_add_link_to_tail(&thread->signal_queue, signalEntry);
 
 	switch (signal) {
 		case SIGKILL:
 		{
 			// Forward KILLTHR to the main thread of the team
 			struct thread *mainThread = thread->team->main_thread;
-			atomic_or(&mainThread->sig_pending, SIGNAL_TO_MASK(SIGKILLTHR));
+			//atomic_or(&mainThread->sig_pending, SIGNAL_TO_MASK(SIGKILLTHR));
+			signalEntry = (struct signal_entry *)malloc(sizeof(signal_entry));
+			if (signalEntry == NULL)
+				return B_OK;
+			signalEntry->info.si_signo = SIGKILLTHR;
+			list_add_link_to_tail(&mainThread->signal_queue, signalEntry);
 
 			// Wake up main thread
 			if (mainThread->state == B_THREAD_SUSPENDED)
@@ -582,8 +612,23 @@
 			if ((flags & SIGNAL_FLAG_DONT_RESTART_SYSCALL) != 0)
 				atomic_or(&thread->flags, THREAD_FLAGS_DONT_RESTART_SYSCALL);
 
-			atomic_and(&thread->sig_pending, ~STOP_SIGNALS);
+			//atomic_and(&thread->sig_pending, ~STOP_SIGNALS);
 				// remove any pending stop signals
+			{
+				siginfo_t *sigInfo = NULL;
+				while ((sigInfo = (siginfo_t *)list_get_next_item(&thread->signal_queue, sigInfo)) != NULL) {
+					switch (sigInfo->si_signo) {
+						case SIGSTOP:
+						case SIGTSTP:
+						case SIGTTIN:
+						case SIGTTOU:
+							list_remove_item(&thread->signal_queue, sigInfo);
+							free((uint8_t*)sigInfo - sizeof(list_link));
+							sigInfo = NULL; // restart search
+							break;
+					}
+				}
+			}
 			break;
 
 		default:
@@ -601,9 +646,11 @@
 }
 
 
-int
-send_signal_etc(pid_t id, uint signal, uint32 flags)
+static int
+send_signal_etc_AF(pid_t id, const siginfo_t* info, uint32 flags)
 {
+	ASSERT(info != NULL);
+	uint signal = info->si_signo;
 	status_t status = B_BAD_THREAD_ID;
 	struct thread *thread;
 	cpu_status state = 0;
@@ -623,7 +670,7 @@
 
 		thread = thread_get_thread_struct_locked(id);
 		if (thread != NULL)
-			status = deliver_signal(thread, signal, flags);
+			status = deliver_signal(thread, info, flags);
 	} else {
 		// send a signal to the specified process group
 		// (the absolute value of the id)
@@ -656,7 +703,7 @@
 				if (thread != NULL) {
 					// we don't stop because of an error sending the signal; we
 					// rather want to send as much signals as possible
-					status = deliver_signal(thread, signal, flags);
+					status = deliver_signal(thread, info, flags);
 				}
 
 				RELEASE_THREAD_LOCK();
@@ -682,6 +729,22 @@
 
 
 int
+send_signal_etc(pid_t id, uint signal, uint32 flags)
+{
+	siginfo_t info;
+	memset(&info, 0, sizeof(siginfo_t));
+	info.si_signo = signal;
+	return send_signal_etc_AF(id, &info, flags);
+}
+
+
+int
+send_signal_AF(pid_t threadID, const siginfo_t* info)
+{
+	return send_signal_etc_AF(threadID, info, 0);
+}
+
+int
 send_signal(pid_t threadID, uint signal)
 {
 	// The BeBook states that this function wouldn't be exported
diff -r d8416f83885f src/system/kernel/thread.cpp
--- a/src/system/kernel/thread.cpp	Mon Apr 05 13:10:28 2010 +0000
+++ b/src/system/kernel/thread.cpp	Tue Apr 06 02:52:34 2010 +0200
@@ -200,6 +200,7 @@
 	thread->signal_stack_base = 0;
 	thread->signal_stack_size = 0;
 	thread->signal_stack_enabled = false;
+	list_init_etc(&thread->signal_queue, offsetof(struct signal_entry, info));
 }
 
 
diff -r d8416f83885f src/system/kernel/vm/vm.cpp
--- a/src/system/kernel/vm/vm.cpp	Mon Apr 05 13:10:28 2010 +0000
+++ b/src/system/kernel/vm/vm.cpp	Tue Apr 06 02:52:34 2010 +0200
@@ -3876,11 +3876,15 @@
 				// If the thread has a signal handler for SIGSEGV, we simply
 				// send it the signal. Otherwise we notify the user debugger
 				// first.
+				siginfo_t info;
+				memset(&info, 0, sizeof(siginfo_t));
+				info.si_signo = SIGSEGV;
+				info.si_addr = (void *)(unsigned long)faultAddress;
 				struct sigaction action;
 				if (sigaction(SIGSEGV, NULL, &action) == 0
 					&& action.sa_handler != SIG_DFL
 					&& action.sa_handler != SIG_IGN) {
-					send_signal(thread->id, SIGSEGV);
+					send_signal_AF(thread->id, &info);
 				} else if (user_debug_exception_occurred(B_SEGMENT_VIOLATION,
 						SIGSEGV)) {
 					send_signal(thread->id, SIGSEGV);
