1bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross/* 2bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * Copyright (C) 2016 The Android Open Source Project 3bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * 4bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * Licensed under the Apache License, Version 2.0 (the "License"); 5bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * you may not use this file except in compliance with the License. 6bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * You may obtain a copy of the License at 7bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * 8bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * http://www.apache.org/licenses/LICENSE-2.0 9bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * 10bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * Unless required by applicable law or agreed to in writing, software 11bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * distributed under the License is distributed on an "AS IS" BASIS, 12bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * See the License for the specific language governing permissions and 14bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross * limitations under the License. 15bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross */ 16bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 17bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#ifndef LIBMEMUNREACHABLE_LEAK_PIPE_H_ 18bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#define LIBMEMUNREACHABLE_LEAK_PIPE_H_ 19bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 20bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#include <sys/socket.h> 21bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 22bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#include <vector> 23bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 24bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#include "android-base/macros.h" 25bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 26bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#include "ScopedPipe.h" 27bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross#include "log.h" 28bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 29a9939e9a23ea21f4f8dc69cf1dae8e95debadcfbColin Crossnamespace android { 30a9939e9a23ea21f4f8dc69cf1dae8e95debadcfbColin Cross 31bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross// LeakPipe implements a pipe that can transfer vectors of simple objects 32bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross// between processes. The pipe is created in the sending process and 33bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross// transferred over a socketpair that was created before forking. This ensures 34bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross// that only the sending process can have the send side of the pipe open, so if 35bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross// the sending process dies the pipe will close. 36bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Crossclass LeakPipe { 37bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross public: 38bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross LeakPipe() { 39a83881e33ce29ee236c924d669cb41a9d816962dColin Cross int ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv_); 40bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (ret < 0) { 4147dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_LOG_ALWAYS_FATAL("failed to create socketpair: %s", strerror(errno)); 42bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 43bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 44bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 45a83881e33ce29ee236c924d669cb41a9d816962dColin Cross ~LeakPipe() { Close(); } 46bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 47bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross void Close() { 48bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross close(sv_[0]); 49bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross close(sv_[1]); 50bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross sv_[0] = -1; 51bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross sv_[1] = -1; 52bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 53bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 54bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool OpenReceiver() { 55bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross int fd = ReceiveFd(sv_[0]); 56bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (fd < 0) { 57bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 58bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 59bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 60bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross receiver_.SetFd(fd); 61bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return true; 62bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 63bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 64bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool OpenSender() { 65bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross ScopedPipe pipe; 66bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 67bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (!SendFd(sv_[1], pipe.Receiver())) { 68bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 69bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 70bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross pipe.ReleaseReceiver(); 71bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 72bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross sender_.SetFd(pipe.ReleaseSender()); 73bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return true; 74bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 75bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 76bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross class LeakPipeBase { 77bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross public: 78bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross LeakPipeBase() : fd_(-1) {} 79bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 80a83881e33ce29ee236c924d669cb41a9d816962dColin Cross ~LeakPipeBase() { Close(); } 81bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 82a83881e33ce29ee236c924d669cb41a9d816962dColin Cross void SetFd(int fd) { fd_ = fd; } 83bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 84bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross void Close() { 85bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross close(fd_); 86bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross fd_ = -1; 87bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 88bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 89bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross protected: 90bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross int fd_; 91bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 92bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross private: 93bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross DISALLOW_COPY_AND_ASSIGN(LeakPipeBase); 94bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross }; 95bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 96bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross class LeakPipeSender : public LeakPipeBase { 97bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross public: 98bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross using LeakPipeBase::LeakPipeBase; 99bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 100a83881e33ce29ee236c924d669cb41a9d816962dColin Cross template <typename T> 101bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool Send(const T& value) { 102bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, &value, sizeof(T))); 103bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (ret < 0) { 10447dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("failed to send value: %s", strerror(errno)); 105bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 106bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } else if (static_cast<size_t>(ret) != sizeof(T)) { 10747dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("eof while writing value"); 108bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 109bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 110bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 111bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return true; 112bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 113bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 114a83881e33ce29ee236c924d669cb41a9d816962dColin Cross template <class T, class Alloc = std::allocator<T>> 115bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool SendVector(const std::vector<T, Alloc>& vector) { 116bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross size_t size = vector.size() * sizeof(T); 117bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (!Send(size)) { 118bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 119bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 120bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 121bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(write(fd_, vector.data(), size)); 122bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (ret < 0) { 12347dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("failed to send vector: %s", strerror(errno)); 124bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 125bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } else if (static_cast<size_t>(ret) != size) { 12647dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("eof while writing vector"); 127bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 128bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 129bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 130bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return true; 131bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 132bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross }; 133bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 134bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross class LeakPipeReceiver : public LeakPipeBase { 135bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross public: 136bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross using LeakPipeBase::LeakPipeBase; 137bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 138a83881e33ce29ee236c924d669cb41a9d816962dColin Cross template <typename T> 139bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool Receive(T* value) { 140bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, reinterpret_cast<void*>(value), sizeof(T))); 141bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (ret < 0) { 14247dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("failed to receive value: %s", strerror(errno)); 143bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 144bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } else if (static_cast<size_t>(ret) != sizeof(T)) { 14547dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("eof while receiving value"); 146bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 147bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 148bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 149bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return true; 150bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 151bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 152a83881e33ce29ee236c924d669cb41a9d816962dColin Cross template <class T, class Alloc = std::allocator<T>> 153bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool ReceiveVector(std::vector<T, Alloc>& vector) { 154bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross size_t size = 0; 155bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (!Receive(&size)) { 156bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 157bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 158bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 159bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross vector.resize(size / sizeof(T)); 160bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 161bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross char* ptr = reinterpret_cast<char*>(vector.data()); 162bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross while (size > 0) { 163bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross ssize_t ret = TEMP_FAILURE_RETRY(read(fd_, ptr, size)); 164bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross if (ret < 0) { 16547dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("failed to send vector: %s", strerror(errno)); 166bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 167bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } else if (ret == 0) { 16847dea71b165c855ec40e855f7514fb745dacac38Christopher Ferris MEM_ALOGE("eof while reading vector"); 169bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return false; 170bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 171bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross size -= ret; 172bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross ptr += ret; 173bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 174bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 175bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross return true; 176bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross } 177bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross }; 178bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 179a83881e33ce29ee236c924d669cb41a9d816962dColin Cross LeakPipeReceiver& Receiver() { return receiver_; } 180bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 181a83881e33ce29ee236c924d669cb41a9d816962dColin Cross LeakPipeSender& Sender() { return sender_; } 182bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 183bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross private: 184bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross LeakPipeReceiver receiver_; 185bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross LeakPipeSender sender_; 186bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross bool SendFd(int sock, int fd); 187bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross int ReceiveFd(int sock); 188bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross DISALLOW_COPY_AND_ASSIGN(LeakPipe); 189bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross int sv_[2]; 190bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross}; 191bcb4ed3eaa92d23949d4ab33dbf1b2604bba8a18Colin Cross 192a9939e9a23ea21f4f8dc69cf1dae8e95debadcfbColin Cross} // namespace android 193a9939e9a23ea21f4f8dc69cf1dae8e95debadcfbColin Cross 194a83881e33ce29ee236c924d669cb41a9d816962dColin Cross#endif // LIBMEMUNREACHABLE_LEAK_PIPE_H_ 195