Add support for EPIPE and SIGPIPE (XCC)
authorKevin Klues <klueska@cs.berkeley.edu>
Tue, 27 Oct 2015 18:05:23 +0000 (11:05 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 16 Nov 2015 23:15:03 +0000 (15:15 -0800)
With this change, we now support proper handling of SIGPIPE.  This
allows us to now run things such as:

$ hexdump -C bin/hexdump | head

However, this only currently works for files in the vfs. Things are
still broken for chans in the 9ns.  For example,

$ hexdump -C mnt/go.cpio | head

will page fault in the kernel with an error of "rpc tags".  The SIGPIPE
is still generated properly. but the call to sys_proc_destroy in the
SIGPIPE signal handler never completes. Specifically, the kernel never
returns from the call to close_fdt() in proc_destroy(). My guess is a
call to cclose() on the fd for 'mnt/go.cpio' is sleeping on its
kref->release(), and never recovering properly.

For now we can ignore this, since a workaround is to just copy the file
into the vfs, but we will need to figure this out eventually.

Signed-off-by: Kevin Klues <klueska@cs.berkeley.edu>
Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/drivers/dev/pipe.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/write.c

index 81c591a..398477c 100644 (file)
@@ -364,8 +364,7 @@ static struct block *pipebread(struct chan *c, long n, uint32_t offset)
 }
 
 /*
- *  a write to a closed pipe causes an exception to be sent to
- *  the prog.
+ *  A write to a closed pipe causes an EPIPE error to be thrown.
  */
 static long pipewrite(struct chan *c, void *va, long n, int64_t ignored)
 {
@@ -382,6 +381,7 @@ static long pipewrite(struct chan *c, void *va, long n, int64_t ignored)
                                r->kill = "write on closed pipe";
 */
                }
+               set_errno(EPIPE);
                nexterror();
        }
 
@@ -420,6 +420,7 @@ static long pipebwrite(struct chan *c, struct block *bp, uint32_t junk)
                                r->kill = "write on closed pipe";
                }
 */
+               set_errno(EPIPE);
                nexterror();
        }
 
index 61790af..9d44807 100644 (file)
 #include <errno.h>
 #include <unistd.h>
 #include <stddef.h>
+#include <signal.h>
+#include <parlib/event.h>
 #include <ros/syscall.h>
+#include <parlib/signal.h>
 
-/* Write NBYTES of BUF to FD.  Return the number written, or -1.  */
-ssize_t
-__libc_write (int fd, const void *buf, size_t nbytes)
+#define unlikely(x) __builtin_expect(!!(x), 0)
+
+/* Write NBYTES of BUF to FD. Return the number written, or -1. Since signals
+ * are a user-space construct in Akaros, handle the SIGPIPE case as well. */
+ssize_t __libc_write(int fd, const void *buf, size_t nbytes)
 {
-  return ros_syscall(SYS_write, fd, buf, nbytes, 0, 0, 0);
+       int ret = ros_syscall(SYS_write, fd, buf, nbytes, 0, 0, 0);
+
+       if (unlikely((ret != 0) && (errno == EPIPE))) {
+               sigset_t mask;
+
+               sigprocmask(0, NULL, &mask);
+               if (!__sigismember(&mask, SIGPIPE))
+                       signal_ops->sigself(SIGPIPE);
+       }
+       return ret;
 }
 libc_hidden_def (__libc_write)