/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <stdlib.h>
#include <unistd.h>
#include <array>
#include <memory>
#include <vector>

#include <getopt.h>
#include <signal.h>

#include "perfetto/base/event.h"
#include "perfetto/base/scoped_file.h"
#include "perfetto/base/unix_socket.h"
#include "perfetto/base/watchdog.h"
#include "src/profiling/memory/heapprofd_producer.h"
#include "src/profiling/memory/wire_protocol.h"
#include "src/tracing/ipc/default_socket.h"

#include "perfetto/base/unix_task_runner.h"

// TODO(rsavitski): the task runner watchdog spawns a thread (normally for
// tracking cpu/mem usage) that we don't strictly need.

namespace perfetto {
namespace profiling {
namespace {

int StartChildHeapprofd(pid_t target_pid,
                        std::string target_cmdline,
                        base::ScopedFile inherited_sock_fd);
int StartCentralHeapprofd();

base::Event* g_dump_evt = nullptr;

int HeapprofdMain(int argc, char** argv) {
  bool cleanup_crash = false;
  pid_t target_pid = base::kInvalidPid;
  std::string target_cmdline;
  base::ScopedFile inherited_sock_fd;

  enum { kCleanupCrash = 256, kTargetPid, kTargetCmd, kInheritFd };
  static struct option long_options[] = {
      {"cleanup-after-crash", no_argument, nullptr, kCleanupCrash},
      {"exclusive-for-pid", required_argument, nullptr, kTargetPid},
      {"exclusive-for-cmdline", required_argument, nullptr, kTargetCmd},
      {"inherit-socket-fd", required_argument, nullptr, kInheritFd},
      {nullptr, 0, nullptr, 0}};
  int option_index;
  int c;
  while ((c = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
    switch (c) {
      case kCleanupCrash:
        cleanup_crash = true;
        break;
      case kTargetPid:
        if (target_pid != base::kInvalidPid)
          PERFETTO_FATAL("Duplicate exclusive-for-pid");
        target_pid = static_cast<pid_t>(atoi(optarg));
        break;
      case kTargetCmd:  // assumed to be already normalized
        if (!target_cmdline.empty())
          PERFETTO_FATAL("Duplicate exclusive-for-cmdline");
        target_cmdline = std::string(optarg);
        break;
      case kInheritFd:  // repetition not supported
        if (inherited_sock_fd)
          PERFETTO_FATAL("Duplicate inherit-socket-fd");
        inherited_sock_fd = base::ScopedFile(atoi(optarg));
        break;
      default:
        PERFETTO_ELOG("Usage: %s [--cleanup-after-crash]", argv[0]);
        return 1;
    }
  }

  if (cleanup_crash) {
    PERFETTO_LOG(
        "Recovering from crash: unsetting heapprofd system properties. "
        "Expect SELinux denials for unrelated properties.");
    SystemProperties::ResetHeapprofdProperties();
    PERFETTO_LOG(
        "Finished unsetting heapprofd system properties. "
        "SELinux denials about properties are unexpected after "
        "this point.");
    return 0;
  }

  // If |target_pid| is given, we're supposed to be operating as a private
  // heapprofd for that process. Note that we might not be a direct child due to
  // reparenting.
  bool tpid_set = target_pid != base::kInvalidPid;
  bool tcmd_set = !target_cmdline.empty();
  bool fds_set = !!inherited_sock_fd;
  if (tpid_set || tcmd_set || fds_set) {
    if (!tpid_set || !tcmd_set || !fds_set) {
      PERFETTO_ELOG(
          "If starting in child mode, requires all of: {--exclusive-for-pid, "
          "--exclusive-for-cmdline, --inherit_socket_fd}");
      return 1;
    }

    return StartChildHeapprofd(target_pid, target_cmdline,
                               std::move(inherited_sock_fd));
  }

  // Otherwise start as a central daemon.
  return StartCentralHeapprofd();
}

int StartChildHeapprofd(pid_t target_pid,
                        std::string target_cmdline,
                        base::ScopedFile inherited_sock_fd) {
  base::UnixTaskRunner task_runner;
  base::Watchdog::GetInstance()->Start();  // crash on exceedingly long tasks
  HeapprofdProducer producer(HeapprofdMode::kChild, &task_runner);
  producer.SetTargetProcess(target_pid, target_cmdline,
                            std::move(inherited_sock_fd));
  producer.ConnectWithRetries(GetProducerSocket());
  producer.ScheduleActiveDataSourceWatchdog();
  task_runner.Run();
  return 0;
}

int StartCentralHeapprofd() {
  // We set this up before launching any threads, so we do not have to use a
  // std::atomic for g_dump_evt.
  g_dump_evt = new base::Event();

  base::UnixTaskRunner task_runner;
  base::Watchdog::GetInstance()->Start();  // crash on exceedingly long tasks
  HeapprofdProducer producer(HeapprofdMode::kCentral, &task_runner);

  struct sigaction action = {};
  action.sa_handler = [](int) { g_dump_evt->Notify(); };
  // Allow to trigger a full dump by sending SIGUSR1 to heapprofd.
  // This will allow manually deciding when to dump on userdebug.
  PERFETTO_CHECK(sigaction(SIGUSR1, &action, nullptr) == 0);
  task_runner.AddFileDescriptorWatch(g_dump_evt->fd(), [&producer] {
    g_dump_evt->Clear();
    producer.DumpAll();
  });
  producer.ConnectWithRetries(GetProducerSocket());
  task_runner.Run();
  return 0;
}

}  // namespace
}  // namespace profiling
}  // namespace perfetto

int main(int argc, char** argv) {
  return perfetto::profiling::HeapprofdMain(argc, argv);
}
