diff -u -r a/include/subprocess.hpp b/include/subprocess.hpp
--- a/include/subprocess.hpp	2019-06-21 12:02:01.465020296 -0700
+++ b/include/subprocess.hpp	2019-06-21 12:06:29.103980843 -0700
@@ -14,18 +14,33 @@
 #include <ext/stdio_filebuf.h>
 #include <cstdio>
 #include <system_error>
+#include <functional>
 
 #include <unistd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <poll.h>
 
 namespace subprocess
 {
 
 class popen
-{   
+{
 public:
 
+    popen(std::function<void()> func)
+        : in_filebuf(nullptr), out_filebuf(nullptr), err_filebuf(nullptr), in_stream(nullptr), out_stream(nullptr), err_stream(nullptr)
+    {
+        if (pipe(in_pipe)  == -1 ||
+            pipe(out_pipe) == -1 ||
+            pipe(err_pipe) == -1 )
+        {
+            throw std::system_error(errno, std::system_category());
+        }
+
+        run(func);
+    }
+
     popen(const std::string& cmd, std::vector<std::string> argv)
         : in_filebuf(nullptr), out_filebuf(nullptr), err_filebuf(nullptr), in_stream(nullptr), out_stream(nullptr), err_stream(nullptr)
     {
@@ -72,24 +87,44 @@
         if (out_stream == nullptr) throw std::system_error(EBADF, std::system_category());
         return *out_stream;
     };
-    
+
     std::istream& stderr() { return *err_stream; };
-   
+
+    pid_t get_pid() {
+        return pid;
+    }
+
     int wait()
     {
         int status = 0;
         waitpid(pid, &status, 0);
-        return WEXITSTATUS(status);
-    };
+        if (WIFEXITED(status)) {
+            return WEXITSTATUS(status);
+        } else if (WIFSIGNALED(status)) {
+            return -WTERMSIG(status);
+        } else {
+            return 0;
+        }
+    }
 
     void close()
     {
         in_filebuf->close();
     }
-    
-    
+
+    // Return true if stdin pipe from child process was closed (e.g. SIGPIPE).
+    bool closed() {
+        struct pollfd pfd;
+        memset(&pfd, 0, sizeof(pfd));
+        pfd.fd = in_pipe[WRITE];
+        if (::poll(&pfd, 1, 0) >= 0 && (pfd.revents & POLLERR)) {
+            return true;
+        }
+        return false;
+    }
+
 private:
-    
+
     enum ends_of_pipe { READ = 0, WRITE = 1 };
 
     struct raii_char_str
@@ -99,33 +134,48 @@
         mutable std::vector<char> buf;
     };
 
-    void run(const std::string& cmd, std::vector<std::string> argv)
+    void run(std::function<void()> func)
     {
-        argv.insert(argv.begin(), cmd);
-
         pid = ::fork();
-      
-        if (pid == 0) child(argv);
+
+        if (pid == 0) child(func);
 
         ::close(in_pipe[READ]);
         ::close(out_pipe[WRITE]);
         ::close(err_pipe[WRITE]);
-        
+
         in_filebuf = new __gnu_cxx::stdio_filebuf<char>(in_pipe[WRITE], std::ios_base::out, 1);
         in_stream  = new std::ostream(in_filebuf);
-        
+
         if (out_pipe[READ] != -1)
         {
             out_filebuf = new __gnu_cxx::stdio_filebuf<char>(out_pipe[READ], std::ios_base::in, 1);
             out_stream  = new std::istream(out_filebuf);
         }
-        
+
         err_filebuf = new __gnu_cxx::stdio_filebuf<char>(err_pipe[READ], std::ios_base::in, 1);
         err_stream  = new std::istream(err_filebuf);
     }
-    
-    void child(const std::vector<std::string>& argv)
-    {  
+
+    void run(const std::string& cmd, std::vector<std::string> argv)
+    {
+        run([&cmd, &argv]() {
+            std::vector<raii_char_str> real_args(argv.begin(), argv.end());
+            real_args.insert(real_args.begin(), cmd);
+            std::vector<char*> cargs(real_args.begin(), real_args.end());
+            cargs.push_back(nullptr);
+
+            if (execvp(cargs[0], &cargs[0]) == -1)
+            {
+                std::perror("subprocess: execvp() failed");
+                // Exit child process.
+                exit(-1);
+            }
+        });
+    }
+
+    void child(std::function<void()> func)
+    {
         if (dup2(in_pipe[READ], STDIN_FILENO)    == -1 ||
             dup2(out_pipe[WRITE], STDOUT_FILENO) == -1 ||
             dup2(err_pipe[WRITE], STDERR_FILENO) == -1 )
@@ -138,18 +188,11 @@
         ::close(in_pipe[WRITE]);
         if (out_pipe[READ] != -1) ::close(out_pipe[READ]);
         ::close(out_pipe[WRITE]);
-        ::close(err_pipe[READ]);        
+        ::close(err_pipe[READ]);
         ::close(err_pipe[WRITE]);
-        
-        std::vector<raii_char_str> real_args(argv.begin(), argv.end());
-        std::vector<char*> cargs(real_args.begin(), real_args.end());
-        cargs.push_back(nullptr);
-        
-        if (execvp(cargs[0], &cargs[0]) == -1)
-        {
-            std::perror("subprocess: execvp() failed");
-            return;
-        }
+
+        func();
+        exit(0);
     }
 
     pid_t pid;
@@ -157,7 +200,7 @@
     int in_pipe[2];
     int out_pipe[2];
     int err_pipe[2];
-   
+
     __gnu_cxx::stdio_filebuf<char>* in_filebuf;
     __gnu_cxx::stdio_filebuf<char>* out_filebuf;
     __gnu_cxx::stdio_filebuf<char>* err_filebuf;
