From 83fc720785c4e40f3341daf7c0bf5ee99261fee9 Mon Sep 17 00:00:00 2001 From: Mark Salyzyn Date: Wed, 29 Jan 2014 11:25:01 -0800 Subject: [PATCH] libsysutil: frequent native crash /system/bin/vold BUG: 12796279 regression from commit a6e965578e44f9ae5f98de822ba5decec381dffc * wrap writev with sigaction SIG_IGN SIGPIPE to emulate the send(,,,MSG_NOSIGNAL) call it had replaced. Change-Id: I14363630ada79c0a5b85bb6b2afd0a1c4d5c3109 --- libsysutils/src/SocketClient.cpp | 36 +++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp index 3625d936c..d3ce8f5a8 100644 --- a/libsysutils/src/SocketClient.cpp +++ b/libsysutils/src/SocketClient.cpp @@ -1,10 +1,11 @@ #include #include -#include -#include #include +#include #include #include +#include +#include #define LOG_TAG "SocketClient" #include @@ -43,8 +44,7 @@ void SocketClient::init(int socket, bool owned, bool useCmdNum) { } } -SocketClient::~SocketClient() -{ +SocketClient::~SocketClient() { if (mSocketOwned) { close(mSocket); } @@ -180,10 +180,19 @@ int SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) { return 0; } + int ret = 0; + int e = 0; // SLOGW and sigaction are not inert regarding errno int current = 0; + struct sigaction new_action, old_action; + memset(&new_action, 0, sizeof(new_action)); + new_action.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &new_action, &old_action); + for (;;) { - ssize_t rc = writev(mSocket, iov + current, iovcnt - current); + ssize_t rc = TEMP_FAILURE_RETRY( + writev(mSocket, iov + current, iovcnt - current)); + if (rc > 0) { size_t written = rc; while ((current < iovcnt) && (written >= iov[current].iov_len)) { @@ -198,18 +207,21 @@ int SocketClient::sendDataLockedv(struct iovec *iov, int iovcnt) { continue; } - if (rc < 0 && errno == EINTR) - continue; - if (rc == 0) { + e = EIO; SLOGW("0 length write :("); - errno = EIO; } else { - SLOGW("write error (%s)", strerror(errno)); + e = errno; + SLOGW("write error (%s)", strerror(e)); } - return -1; + ret = -1; + break; } - return 0; + + sigaction(SIGPIPE, &old_action, &new_action); + + errno = e; + return ret; } void SocketClient::incRef() {