17add50d820938123b7f163bbc5b528623065b7b1Colin Cross/* 27add50d820938123b7f163bbc5b528623065b7b1Colin Cross * Copyright (C) 2016 The Android Open Source Project 37add50d820938123b7f163bbc5b528623065b7b1Colin Cross * 47add50d820938123b7f163bbc5b528623065b7b1Colin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 57add50d820938123b7f163bbc5b528623065b7b1Colin Cross * you may not use this file except in compliance with the License. 67add50d820938123b7f163bbc5b528623065b7b1Colin Cross * You may obtain a copy of the License at 77add50d820938123b7f163bbc5b528623065b7b1Colin Cross * 87add50d820938123b7f163bbc5b528623065b7b1Colin Cross * http://www.apache.org/licenses/LICENSE-2.0 97add50d820938123b7f163bbc5b528623065b7b1Colin Cross * 107add50d820938123b7f163bbc5b528623065b7b1Colin Cross * Unless required by applicable law or agreed to in writing, software 117add50d820938123b7f163bbc5b528623065b7b1Colin Cross * distributed under the License is distributed on an "AS IS" BASIS, 127add50d820938123b7f163bbc5b528623065b7b1Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 137add50d820938123b7f163bbc5b528623065b7b1Colin Cross * See the License for the specific language governing permissions and 147add50d820938123b7f163bbc5b528623065b7b1Colin Cross * limitations under the License. 157add50d820938123b7f163bbc5b528623065b7b1Colin Cross */ 167add50d820938123b7f163bbc5b528623065b7b1Colin Cross 177add50d820938123b7f163bbc5b528623065b7b1Colin Cross#ifndef LIBMEMUNREACHABLE_LEAK_PIPE_H_ 187add50d820938123b7f163bbc5b528623065b7b1Colin Cross#define LIBMEMUNREACHABLE_LEAK_PIPE_H_ 197add50d820938123b7f163bbc5b528623065b7b1Colin Cross 207add50d820938123b7f163bbc5b528623065b7b1Colin Cross#include <sys/socket.h> 217add50d820938123b7f163bbc5b528623065b7b1Colin Cross 227add50d820938123b7f163bbc5b528623065b7b1Colin Cross#include <vector> 237add50d820938123b7f163bbc5b528623065b7b1Colin Cross 247add50d820938123b7f163bbc5b528623065b7b1Colin Cross#include "android-base/macros.h" 257add50d820938123b7f163bbc5b528623065b7b1Colin Cross 267add50d820938123b7f163bbc5b528623065b7b1Colin Cross#include "ScopedPipe.h" 277add50d820938123b7f163bbc5b528623065b7b1Colin Cross#include "log.h" 287add50d820938123b7f163bbc5b528623065b7b1Colin Cross 297add50d820938123b7f163bbc5b528623065b7b1Colin Cross// LeakPipe implements a pipe that can transfer vectors of simple objects 307add50d820938123b7f163bbc5b528623065b7b1Colin Cross// between processes. The pipe is created in the sending process and 317add50d820938123b7f163bbc5b528623065b7b1Colin Cross// transferred over a socketpair that was created before forking. This ensures 327add50d820938123b7f163bbc5b528623065b7b1Colin Cross// that only the sending process can have the send side of the pipe open, so if 337add50d820938123b7f163bbc5b528623065b7b1Colin Cross// the sending process dies the pipe will close. 347add50d820938123b7f163bbc5b528623065b7b1Colin Crossclass LeakPipe { 357add50d820938123b7f163bbc5b528623065b7b1Colin Cross public: 367add50d820938123b7f163bbc5b528623065b7b1Colin Cross LeakPipe() { 377add50d820938123b7f163bbc5b528623065b7b1Colin Cross int ret = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, sv_); 387add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (ret < 0) { 397add50d820938123b7f163bbc5b528623065b7b1Colin Cross LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno)); 407add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 417add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 427add50d820938123b7f163bbc5b528623065b7b1Colin Cross 437add50d820938123b7f163bbc5b528623065b7b1Colin Cross ~LeakPipe() { 447add50d820938123b7f163bbc5b528623065b7b1Colin Cross Close(); 457add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 467add50d820938123b7f163bbc5b528623065b7b1Colin Cross 477add50d820938123b7f163bbc5b528623065b7b1Colin Cross void Close() { 487add50d820938123b7f163bbc5b528623065b7b1Colin Cross close(sv_[0]); 497add50d820938123b7f163bbc5b528623065b7b1Colin Cross close(sv_[1]); 507add50d820938123b7f163bbc5b528623065b7b1Colin Cross sv_[0] = -1; 517add50d820938123b7f163bbc5b528623065b7b1Colin Cross sv_[1] = -1; 527add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 537add50d820938123b7f163bbc5b528623065b7b1Colin Cross 547add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool OpenReceiver() { 557add50d820938123b7f163bbc5b528623065b7b1Colin Cross int fd = ReceiveFd(sv_[0]); 567add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (fd < 0) { 577add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 587add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 597add50d820938123b7f163bbc5b528623065b7b1Colin Cross 607add50d820938123b7f163bbc5b528623065b7b1Colin Cross receiver_.SetFd(fd); 617add50d820938123b7f163bbc5b528623065b7b1Colin Cross return true; 627add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 637add50d820938123b7f163bbc5b528623065b7b1Colin Cross 647add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool OpenSender() { 657add50d820938123b7f163bbc5b528623065b7b1Colin Cross ScopedPipe pipe; 667add50d820938123b7f163bbc5b528623065b7b1Colin Cross 677add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (!SendFd(sv_[1], pipe.Receiver())) { 687add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 697add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 707add50d820938123b7f163bbc5b528623065b7b1Colin Cross pipe.ReleaseReceiver(); 717add50d820938123b7f163bbc5b528623065b7b1Colin Cross 727add50d820938123b7f163bbc5b528623065b7b1Colin Cross sender_.SetFd(pipe.ReleaseSender()); 737add50d820938123b7f163bbc5b528623065b7b1Colin Cross return true; 747add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 757add50d820938123b7f163bbc5b528623065b7b1Colin Cross 767add50d820938123b7f163bbc5b528623065b7b1Colin Cross class LeakPipeBase { 777add50d820938123b7f163bbc5b528623065b7b1Colin Cross public: 787add50d820938123b7f163bbc5b528623065b7b1Colin Cross LeakPipeBase() : fd_(-1) {} 797add50d820938123b7f163bbc5b528623065b7b1Colin Cross 807add50d820938123b7f163bbc5b528623065b7b1Colin Cross ~LeakPipeBase() { 817add50d820938123b7f163bbc5b528623065b7b1Colin Cross Close(); 827add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 837add50d820938123b7f163bbc5b528623065b7b1Colin Cross 847add50d820938123b7f163bbc5b528623065b7b1Colin Cross void SetFd(int fd) { 857add50d820938123b7f163bbc5b528623065b7b1Colin Cross fd_ = fd; 867add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 877add50d820938123b7f163bbc5b528623065b7b1Colin Cross 887add50d820938123b7f163bbc5b528623065b7b1Colin Cross void Close() { 897add50d820938123b7f163bbc5b528623065b7b1Colin Cross close(fd_); 907add50d820938123b7f163bbc5b528623065b7b1Colin Cross fd_ = -1; 917add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 927add50d820938123b7f163bbc5b528623065b7b1Colin Cross 937add50d820938123b7f163bbc5b528623065b7b1Colin Cross protected: 947add50d820938123b7f163bbc5b528623065b7b1Colin Cross int fd_; 957add50d820938123b7f163bbc5b528623065b7b1Colin Cross 967add50d820938123b7f163bbc5b528623065b7b1Colin Cross private: 977add50d820938123b7f163bbc5b528623065b7b1Colin Cross DISALLOW_COPY_AND_ASSIGN(LeakPipeBase); 987add50d820938123b7f163bbc5b528623065b7b1Colin Cross }; 997add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1007add50d820938123b7f163bbc5b528623065b7b1Colin Cross class LeakPipeSender : public LeakPipeBase { 1017add50d820938123b7f163bbc5b528623065b7b1Colin Cross public: 1027add50d820938123b7f163bbc5b528623065b7b1Colin Cross using LeakPipeBase::LeakPipeBase; 1037add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1047add50d820938123b7f163bbc5b528623065b7b1Colin Cross template<typename T> 1057add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool Send(const T& value) { 1067add50d820938123b7f163bbc5b528623065b7b1Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T))); 1077add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (ret < 0) { 1087add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("failed to send value: %s", strerror(errno)); 1097add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1107add50d820938123b7f163bbc5b528623065b7b1Colin Cross } else if (static_cast<size_t>(ret) != sizeof(T)) { 1117add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("eof while writing value"); 1127add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1137add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1147add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1157add50d820938123b7f163bbc5b528623065b7b1Colin Cross return true; 1167add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1177add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1187add50d820938123b7f163bbc5b528623065b7b1Colin Cross template<class T, class Alloc = std::allocator<T>> 1197add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool SendVector(const std::vector<T, Alloc>& vector) { 1207add50d820938123b7f163bbc5b528623065b7b1Colin Cross size_t size = vector.size() * sizeof(T); 1217add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (!Send(size)) { 1227add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1237add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1247add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1257add50d820938123b7f163bbc5b528623065b7b1Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, vector.data(), size)); 1267add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (ret < 0) { 1277add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("failed to send vector: %s", strerror(errno)); 1287add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1297add50d820938123b7f163bbc5b528623065b7b1Colin Cross } else if (static_cast<size_t>(ret) != size) { 1307add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("eof while writing vector"); 1317add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1327add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1337add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1347add50d820938123b7f163bbc5b528623065b7b1Colin Cross return true; 1357add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1367add50d820938123b7f163bbc5b528623065b7b1Colin Cross }; 1377add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1387add50d820938123b7f163bbc5b528623065b7b1Colin Cross class LeakPipeReceiver : public LeakPipeBase { 1397add50d820938123b7f163bbc5b528623065b7b1Colin Cross public: 1407add50d820938123b7f163bbc5b528623065b7b1Colin Cross using LeakPipeBase::LeakPipeBase; 1417add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1427add50d820938123b7f163bbc5b528623065b7b1Colin Cross template<typename T> 1437add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool Receive(T* value) { 1447add50d820938123b7f163bbc5b528623065b7b1Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T))); 1457add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (ret < 0) { 1467add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("failed to receive value: %s", strerror(errno)); 1477add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1487add50d820938123b7f163bbc5b528623065b7b1Colin Cross } else if (static_cast<size_t>(ret) != sizeof(T)) { 1497add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("eof while receiving value"); 1507add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1517add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1527add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1537add50d820938123b7f163bbc5b528623065b7b1Colin Cross return true; 1547add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1557add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1567add50d820938123b7f163bbc5b528623065b7b1Colin Cross template<class T, class Alloc = std::allocator<T>> 1577add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool ReceiveVector(std::vector<T, Alloc>& vector) { 1587add50d820938123b7f163bbc5b528623065b7b1Colin Cross size_t size = 0; 1597add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (!Receive(&size)) { 1607add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1617add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1627add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1637add50d820938123b7f163bbc5b528623065b7b1Colin Cross vector.resize(size / sizeof(T)); 1647add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1657add50d820938123b7f163bbc5b528623065b7b1Colin Cross char* ptr = reinterpret_cast<char*>(vector.data()); 1667add50d820938123b7f163bbc5b528623065b7b1Colin Cross while (size > 0) { 1677add50d820938123b7f163bbc5b528623065b7b1Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, ptr, size)); 1687add50d820938123b7f163bbc5b528623065b7b1Colin Cross if (ret < 0) { 1697add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("failed to send vector: %s", strerror(errno)); 1707add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1717add50d820938123b7f163bbc5b528623065b7b1Colin Cross } else if (ret == 0) { 1727add50d820938123b7f163bbc5b528623065b7b1Colin Cross ALOGE("eof while reading vector"); 1737add50d820938123b7f163bbc5b528623065b7b1Colin Cross return false; 1747add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1757add50d820938123b7f163bbc5b528623065b7b1Colin Cross size -= ret; 1767add50d820938123b7f163bbc5b528623065b7b1Colin Cross ptr += ret; 1777add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1787add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1797add50d820938123b7f163bbc5b528623065b7b1Colin Cross return true; 1807add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1817add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1827add50d820938123b7f163bbc5b528623065b7b1Colin Cross }; 1837add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1847add50d820938123b7f163bbc5b528623065b7b1Colin Cross LeakPipeReceiver& Receiver() { 1857add50d820938123b7f163bbc5b528623065b7b1Colin Cross return receiver_; 1867add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1877add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1887add50d820938123b7f163bbc5b528623065b7b1Colin Cross LeakPipeSender& Sender() { 1897add50d820938123b7f163bbc5b528623065b7b1Colin Cross return sender_; 1907add50d820938123b7f163bbc5b528623065b7b1Colin Cross } 1917add50d820938123b7f163bbc5b528623065b7b1Colin Cross 1927add50d820938123b7f163bbc5b528623065b7b1Colin Cross private: 1937add50d820938123b7f163bbc5b528623065b7b1Colin Cross LeakPipeReceiver receiver_; 1947add50d820938123b7f163bbc5b528623065b7b1Colin Cross LeakPipeSender sender_; 1957add50d820938123b7f163bbc5b528623065b7b1Colin Cross bool SendFd(int sock, int fd); 1967add50d820938123b7f163bbc5b528623065b7b1Colin Cross int ReceiveFd(int sock); 1977add50d820938123b7f163bbc5b528623065b7b1Colin Cross DISALLOW_COPY_AND_ASSIGN(LeakPipe); 1987add50d820938123b7f163bbc5b528623065b7b1Colin Cross int sv_[2]; 1997add50d820938123b7f163bbc5b528623065b7b1Colin Cross}; 2007add50d820938123b7f163bbc5b528623065b7b1Colin Cross 2017add50d820938123b7f163bbc5b528623065b7b1Colin Cross#endif // LIBMEMUNREACHABLE_LEAK_PIPE_H_ 202