Index: uspace/lib/posix/signal.c
===================================================================
--- uspace/lib/posix/signal.c	(revision 2aadf2b583c5b7bd65f939f41f832a34d7050d8a)
+++ uspace/lib/posix/signal.c	(revision 4419c347a4231f39281a505ad4149f3d49261123)
@@ -45,9 +45,18 @@
 #include "libc/task.h"
 
-// TODO: documentation
+/* This file implements a fairly dumb and incomplete "simulation" of
+ * POSIX signals. Since HelenOS doesn't support signals and mostly doesn't
+ * have any equivalent functionality, most of the signals are useless. The
+ * main purpose of this implementation is thus to help port applications using
+ * signals with minimal modification, but if the application uses signals for
+ * anything non-trivial, it's quite probable it won't work properly even if
+ * it builds without problems.
+ */
 
 /* Used to serialize signal handling. */
 static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
 
+static LIST_INITIALIZE(_signal_queue);
+
 static posix_sigset_t _signal_mask = 0;
 
@@ -55,4 +64,5 @@
     .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
 
+/* Actions associated with each signal number. */
 static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
 	DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, 
@@ -126,5 +136,5 @@
 }
 
-/**
+/** Just an empty function to get an unique pointer value for comparison.
  *
  * @param signo
@@ -135,5 +145,5 @@
 }
 
-/**
+/** Empty function to be used as ignoring handler.
  * 
  * @param signo
@@ -144,8 +154,8 @@
 }
 
-/**
- * 
- * @param set
- * @return
+/** Clear the signal set.
+ * 
+ * @param set Pointer to the signal set.
+ * @return Always returns zero.
  */
 int posix_sigemptyset(posix_sigset_t *set)
@@ -157,8 +167,8 @@
 }
 
-/**
- * 
- * @param set
- * @return
+/** Fill the signal set (i.e. add all signals).
+ * 
+ * @param set Pointer to the signal set.
+ * @return Always returns zero.
  */
 int posix_sigfillset(posix_sigset_t *set)
@@ -170,9 +180,9 @@
 }
 
-/**
- * 
- * @param set
- * @param signo
- * @return
+/** Add a signal to the set.
+ * 
+ * @param set Pointer to the signal set.
+ * @param signo Signal number to add.
+ * @return Always returns zero.
  */
 int posix_sigaddset(posix_sigset_t *set, int signo)
@@ -184,9 +194,9 @@
 }
 
-/**
- * 
- * @param set
- * @param signo
- * @return
+/** Delete a signal from the set.
+ * 
+ * @param set Pointer to the signal set.
+ * @param signo Signal number to remove.
+ * @return Always returns zero.
  */
 int posix_sigdelset(posix_sigset_t *set, int signo)
@@ -198,9 +208,9 @@
 }
 
-/**
- * 
- * @param set
- * @param signo
- * @return
+/** Inclusion test for a signal set.
+ * 
+ * @param set Pointer to the signal set.
+ * @param signo Signal number to query.
+ * @return 1 if the signal is in the set, 0 otherwise.
  */
 int posix_sigismember(const posix_sigset_t *set, int signo)
@@ -211,5 +221,7 @@
 }
 
-/**
+/** Unsafe variant of the sigaction() function.
+ *  Doesn't do any checking of its arguments and
+ *  does not deal with thread-safety.
  * 
  * @param sig
@@ -231,10 +243,12 @@
 }
 
-/**
- * 
- * @param sig
- * @param act
- * @param oact
- * @return
+/** Sets a new action for the given signal number.
+ * 
+ * @param sig Signal number to set action for.
+ * @param act If not NULL, contents of this structure are
+ *     used as the new action for the signal.
+ * @param oact If not NULL, the original action associated with the signal
+ *     is stored in the structure pointer to. 
+ * @return -1 with errno set on failure, 0 on success.
  */
 int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
@@ -262,9 +276,9 @@
 }
 
-/**
- * 
- * @param sig
- * @param func
- * @return
+/** Sets a new handler for the given signal number.
+ * 
+ * @param sig Signal number to set handler for.
+ * @param func Handler function.
+ * @return SIG_ERR on failure, original handler on success.
  */
 void (*posix_signal(int sig, void (*func)(int)))(int)
@@ -284,14 +298,39 @@
 }
 
-/**
- * 
- * @param signo
- * @param siginfo
- * @return
- */
-static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
+typedef struct {
+	link_t link;
+	int signo;
+	posix_siginfo_t siginfo;
+} signal_queue_item;
+
+/** Queue blocked signal.
+ *
+ * @param signo Signal number.
+ * @param siginfo Additional information about the signal.
+ */
+static void _queue_signal(int signo, posix_siginfo_t *siginfo)
 {
 	assert(signo >= 0 && signo <= _TOP_SIGNAL);
 	assert(siginfo != NULL);
+	
+	signal_queue_item *item = malloc(sizeof(signal_queue_item));
+	link_initialize(&(item->link));
+	item->signo = signo;
+	memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
+	list_append(&(item->link), &_signal_queue);
+}
+
+
+/** Executes an action associated with the given signal.
+ *
+ * @param signo Signal number.
+ * @param siginfo Additional information about the circumstances of this raise.
+ * @return 0 if the action has been successfully executed. -1 if the signal is
+ *     blocked.
+ */
+static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
+{
+	assert(signo >= 0 && signo <= _TOP_SIGNAL);
+	assert(siginfo != NULL);
 
 	fibril_mutex_lock(&_signal_mutex);
@@ -301,5 +340,5 @@
 	if (posix_sigismember(&_signal_mask, signo) ||
 	    action.sa_handler == SIG_HOLD) {
-		// TODO: queue signal
+		_queue_signal(signo, siginfo);
 		fibril_mutex_unlock(&_signal_mutex);
 		return -1;
@@ -327,8 +366,32 @@
 }
 
-/**
- * 
- * @param sig
- * @return
+/** Raise all unblocked previously queued signals.
+ */
+static void _dequeue_unblocked_signals()
+{
+	link_t *iterator = _signal_queue.head.next;
+	link_t *next;
+	
+	while (iterator != &(_signal_queue).head) {
+		next = iterator->next;
+		
+		signal_queue_item *item =
+		    list_get_instance(iterator, signal_queue_item, link);
+		
+		if (!posix_sigismember(&_signal_mask, item->signo) &&
+		    _signal_actions[item->signo].sa_handler != SIG_HOLD) {
+			list_remove(&(item->link));
+			_raise_sigaction(item->signo, &(item->siginfo));
+			free(item);
+		}
+		
+		iterator = next;
+	}
+}
+
+/** Raise a signal for the calling process.
+ * 
+ * @param sig Signal number.
+ * @return -1 with errno set on failure, 0 on success.
  */
 int posix_raise(int sig)
@@ -346,9 +409,10 @@
 }
 
-/**
- * 
- * @param pid
- * @param signo
- * @return
+/** Raises a signal for a selected process.
+ * 
+ * @param pid PID of the process for which the signal shall be raised.
+ * @param signo Signal to raise.
+ * @return -1 with errno set on failure (possible errors include unsupported
+ *     action, invalid signal number, lack of permissions, etc.), 0 on success.
  */
 int posix_kill(posix_pid_t pid, int signo)
@@ -382,9 +446,10 @@
 }
 
-/**
- * 
- * @param pid
- * @param sig
- * @return
+/** Send a signal to a process group. Always fails at the moment because of
+ *  lack of this functionality in HelenOS.
+ * 
+ * @param pid PID of the process group.
+ * @param sig Signal number.
+ * @return -1 on failure, 0 on success (see kill()).
  */
 int posix_killpg(posix_pid_t pid, int sig)
@@ -394,8 +459,8 @@
 }
 
-/**
- * 
- * @param pinfo
- * @param message
+/** Outputs information about the signal to the standard error stream.
+ * 
+ * @param pinfo SigInfo struct to write.
+ * @param message String to output alongside human-readable signal description.
  */
 void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
@@ -406,8 +471,8 @@
 }
 
-/**
- * 
- * @param signum
- * @param message
+/** Outputs information about the signal to the standard error stream.
+ * 
+ * @param signum Signal number.
+ * @param message String to output alongside human-readable signal description.
  */
 void posix_psignal(int signum, const char *message)
@@ -421,10 +486,10 @@
 }
 
-/**
- * 
- * @param how
- * @param set
- * @param oset
- * @return
+/** Manipulate the signal mask of the calling thread.
+ * 
+ * @param how What to do with the mask.
+ * @param set Signal set to work with.
+ * @param oset If not NULL, the original signal mask is coppied here.
+ * @return 0 success, errorcode on failure.
  */
 int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
@@ -452,6 +517,6 @@
 		}
 	}
-
-	// TODO: queued signal handling
+	
+	_dequeue_unblocked_signals();
 
 	fibril_mutex_unlock(&_signal_mutex);
@@ -460,10 +525,10 @@
 }
 
-/**
- * 
- * @param how
- * @param set
- * @param oset
- * @return
+/** Manipulate the signal mask of the process.
+ * 
+ * @param how What to do with the mask.
+ * @param set Signal set to work with.
+ * @param oset If not NULL, the original signal mask is coppied here.
+ * @return 0 on success, -1 with errno set on failure.
  */
 int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
