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