Fix bug in pthread_sigmask() semantics.
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 27 Oct 2015 17:12:37 +0000 (10:12 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 16 Nov 2015 23:15:03 +0000 (15:15 -0800)
Previously, the 'how' parameter was not being ignored correctly if 'set'
was NULL. Moreover, we were not setting the value of 'oset' properly in
cases where 'set' was NULL and 'how' should be ignored. This patch
attempts to fix these semantics to match the specification in:

http://linux.die.net/man/2/sigprocmask

Signed-off-by: Kevin Klues <klueska@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
user/pthread/pthread.c

index 961d087..27cf399 100644 (file)
@@ -1309,27 +1309,31 @@ int pthread_kill(pthread_t thread, int signo)
 
 int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
 {
-       sigset_t *sigmask;
-       if (how != SIG_BLOCK && how != SIG_SETMASK && how != SIG_UNBLOCK) {
+       sigset_t *sigmask = &((struct pthread_tcb*)current_uthread)->sigmask;
+
+       if (set && (how != SIG_BLOCK) &&
+                 (how != SIG_SETMASK) &&
+                 (how != SIG_UNBLOCK)) {
                errno = EINVAL;
                return -1;
        }
-       sigmask = &((struct pthread_tcb*)current_uthread)->sigmask;
 
        if (oset)
                *oset = *sigmask;
-       switch (how) {
-               case SIG_BLOCK:
-                       *sigmask = *sigmask | *set;
-                       break;
-               case SIG_SETMASK:
-                       *sigmask = *set;
-                       break;
-               case SIG_UNBLOCK:
-                       *sigmask = *sigmask & ~(*set);
-                       break;
+       if (set) {
+               switch (how) {
+                       case SIG_BLOCK:
+                               *sigmask = *sigmask | *set;
+                               break;
+                       case SIG_SETMASK:
+                               *sigmask = *set;
+                               break;
+                       case SIG_UNBLOCK:
+                               *sigmask = *sigmask & ~(*set);
+                               break;
+               }
        }
-       // Ensures any signals we just unmasked get processed if they are pending
+       /* Ensures any pending signals we unmasked get processed  */
        pthread_yield();
        return 0;
 }