If a scriptlet/hook dies at the wrong moment it can trigger SIGPIPE,
terminating the process.  For pipes, there is no way to prevent SIGPIPE
other than ignoring it process-wide.  This can have unintended
consequences in a multi-threaded process.  Using send(2) with sockets,
however, allows ignoring SIGPIPE on a per-call basis, leaving other
threads able to make use of SIGPIPE.

Signed-off-by: Andrew Gregory <[email protected]>
---
 lib/libalpm/util.c | 17 ++++-------------
 1 file changed, 4 insertions(+), 13 deletions(-)

diff --git a/lib/libalpm/util.c b/lib/libalpm/util.c
index 58efa5c7..5a7f2c87 100644
--- a/lib/libalpm/util.c
+++ b/lib/libalpm/util.c
@@ -30,6 +30,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <sys/wait.h>
+#include <sys/socket.h>
 #include <fnmatch.h>
 #include <poll.h>
 
@@ -463,7 +464,6 @@ static int _alpm_chroot_write_to_child(alpm_handle_t 
*handle, int fd,
                _alpm_cb_io out_cb, void *cb_ctx)
 {
        ssize_t nwrite;
-       struct sigaction newaction, oldaction;
 
        if(*buf_size == 0) {
                /* empty buffer, ask the callback for more */
@@ -473,16 +473,7 @@ static int _alpm_chroot_write_to_child(alpm_handle_t 
*handle, int fd,
                }
        }
 
-       /* ignore SIGPIPE in case the pipe has been closed */
-       newaction.sa_handler = SIG_IGN;
-       sigemptyset(&newaction.sa_mask);
-       newaction.sa_flags = 0;
-       sigaction(SIGPIPE, &newaction, &oldaction);
-
-       nwrite = write(fd, buf, *buf_size);
-
-       /* restore previous SIGPIPE handler */
-       sigaction(SIGPIPE, &oldaction, NULL);
+       nwrite = send(fd, buf, *buf_size, MSG_NOSIGNAL);
 
        if(nwrite != -1) {
                /* write was successful, remove the written data from the 
buffer */
@@ -592,13 +583,13 @@ int _alpm_run_chroot(alpm_handle_t *handle, const char 
*cmd, char *const argv[],
        /* Flush open fds before fork() to avoid cloning buffers */
        fflush(NULL);
 
-       if(pipe(child2parent_pipefd) == -1) {
+       if(socketpair(AF_UNIX, SOCK_STREAM, 0, child2parent_pipefd) == -1) {
                _alpm_log(handle, ALPM_LOG_ERROR, _("could not create pipe 
(%s)\n"), strerror(errno));
                retval = 1;
                goto cleanup;
        }
 
-       if(pipe(parent2child_pipefd) == -1) {
+       if(socketpair(AF_UNIX, SOCK_STREAM, 0, parent2child_pipefd) == -1) {
                _alpm_log(handle, ALPM_LOG_ERROR, _("could not create pipe 
(%s)\n"), strerror(errno));
                retval = 1;
                goto cleanup;
-- 
2.12.2

Reply via email to