diff options
author | Mark Salyzyn <salyzyn@google.com> | 2014-01-29 11:25:01 -0800 |
---|---|---|
committer | Mark Salyzyn <salyzyn@google.com> | 2014-01-31 15:27:14 -0800 |
commit | 4389588e8ded66148d9e616aa20307cf25144460 (patch) | |
tree | ad010ea143e919c6b71c0bedc583f20fec2a5998 /libsysutils | |
parent | caefe564a4b05e717a3baec155b8968ad36e58b6 (diff) | |
download | core-4389588e8ded66148d9e616aa20307cf25144460.tar.gz core-4389588e8ded66148d9e616aa20307cf25144460.tar.bz2 core-4389588e8ded66148d9e616aa20307cf25144460.zip |
libsysutil: frequent native crash /system/bin/vold
regression from commit a6e965578e44f9ae5f98de822ba5decec381dffc
* wrap writev with sigaction SIG_IGN SIGPIPE to emulate the
send(,,,MSG_NOSIGNAL) call it had replaced.
(cherry pick from commit 83fc720785c4e40f3341daf7c0bf5ee99261fee9)
BUG: 12796279
Change-Id: I14363630ada79c0a5b85bb6b2afd0a1c4d5c3109
Diffstat (limited to 'libsysutils')
-rw-r--r-- | libsysutils/src/SocketClient.cpp | 36 |
1 files 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 <alloca.h> #include <errno.h> -#include <sys/socket.h> -#include <sys/types.h> #include <pthread.h> +#include <signal.h> #include <string.h> #include <arpa/inet.h> +#include <sys/socket.h> +#include <sys/types.h> #define LOG_TAG "SocketClient" #include <cutils/log.h> @@ -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() { |