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