/*
 * Copyright (C) 2013 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 <errno.h>
#include <inttypes.h>
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>

#include <cutils/atomic.h>

#include "BacktraceLog.h"
#include "BacktraceThread.h"
#include "thread_utils.h"

//-------------------------------------------------------------------------
// ThreadEntry implementation.
//-------------------------------------------------------------------------
static ThreadEntry* g_list = NULL;
static pthread_mutex_t g_entry_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t g_sigaction_mutex = PTHREAD_MUTEX_INITIALIZER;

ThreadEntry::ThreadEntry(
    BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames)
    : thread_intf(intf), pid(pid), tid(tid), next(NULL), prev(NULL),
      state(STATE_WAITING), num_ignore_frames(num_ignore_frames) {
}

ThreadEntry::~ThreadEntry() {
  pthread_mutex_lock(&g_entry_mutex);
  if (g_list == this) {
    g_list = next;
  } else {
    if (next) {
      next->prev = prev;
    }
    prev->next = next;
  }
  pthread_mutex_unlock(&g_entry_mutex);

  next = NULL;
  prev = NULL;
}

ThreadEntry* ThreadEntry::AddThreadToUnwind(
    BacktraceThreadInterface* intf, pid_t pid, pid_t tid, size_t num_ignore_frames) {
  ThreadEntry* entry = new ThreadEntry(intf, pid, tid, num_ignore_frames);

  pthread_mutex_lock(&g_entry_mutex);
  ThreadEntry* cur_entry = g_list;
  while (cur_entry != NULL) {
    if (cur_entry->Match(pid, tid)) {
      // There is already an entry for this pid/tid, this is bad.
      BACK_LOGW("Entry for pid %d tid %d already exists.", pid, tid);

      pthread_mutex_unlock(&g_entry_mutex);
      return NULL;
    }
    cur_entry = cur_entry->next;
  }

  // Add the entry to the list.
  entry->next = g_list;
  if (g_list) {
    g_list->prev = entry;
  }
  g_list = entry;
  pthread_mutex_unlock(&g_entry_mutex);

  return entry;
}

//-------------------------------------------------------------------------
// BacktraceThread functions.
//-------------------------------------------------------------------------
static void SignalHandler(int n __attribute__((unused)), siginfo_t* siginfo,
                          void* sigcontext) {
  if (pthread_mutex_lock(&g_entry_mutex) == 0) {
    pid_t pid = getpid();
    pid_t tid = gettid();
    ThreadEntry* cur_entry = g_list;
    while (cur_entry) {
      if (cur_entry->Match(pid, tid)) {
        break;
      }
      cur_entry = cur_entry->next;
    }
    pthread_mutex_unlock(&g_entry_mutex);
    if (!cur_entry) {
      BACK_LOGW("Unable to find pid %d tid %d information", pid, tid);
      return;
    }

    if (android_atomic_acquire_cas(STATE_WAITING, STATE_DUMPING, &cur_entry->state) == 0) {
      cur_entry->thread_intf->ThreadUnwind(siginfo, sigcontext,
                                           cur_entry->num_ignore_frames);
    }
    android_atomic_release_store(STATE_DONE, &cur_entry->state);
  }
}

BacktraceThread::BacktraceThread(
    BacktraceImpl* impl, BacktraceThreadInterface* thread_intf, pid_t tid,
    BacktraceMap* map)
    : BacktraceCurrent(impl, map), thread_intf_(thread_intf) {
  tid_ = tid;
}

BacktraceThread::~BacktraceThread() {
}

void BacktraceThread::FinishUnwind() {
  for (std::vector<backtrace_frame_data_t>::iterator it = frames_.begin();
       it != frames_.end(); ++it) {
    it->map = FindMap(it->pc);

    it->func_offset = 0;
    it->func_name = GetFunctionName(it->pc, &it->func_offset);
  }
}

bool BacktraceThread::TriggerUnwindOnThread(ThreadEntry* entry) {
  entry->state = STATE_WAITING;

  if (tgkill(Pid(), Tid(), SIGURG) != 0) {
    BACK_LOGW("tgkill failed %s", strerror(errno));
    return false;
  }

  // Allow up to ten seconds for the dump to start.
  int wait_millis = 10000;
  int32_t state;
  while (true) {
    state = android_atomic_acquire_load(&entry->state);
    if (state != STATE_WAITING) {
      break;
    }
    if (wait_millis--) {
      usleep(1000);
    } else {
      break;
    }
  }

  bool cancelled = false;
  if (state == STATE_WAITING) {
    if (android_atomic_acquire_cas(state, STATE_CANCEL, &entry->state) == 0) {
      BACK_LOGW("Cancelled dump of thread %d", entry->tid);
      state = STATE_CANCEL;
      cancelled = true;
    } else {
      state = android_atomic_acquire_load(&entry->state);
    }
  }

  // Wait for at most ten seconds for the cancel or dump to finish.
  wait_millis = 10000;
  while (android_atomic_acquire_load(&entry->state) != STATE_DONE) {
    if (wait_millis--) {
      usleep(1000);
    } else {
      BACK_LOGW("Didn't finish thread unwind in 60 seconds.");
      break;
    }
  }
  return !cancelled;
}

bool BacktraceThread::Unwind(size_t num_ignore_frames) {
  ThreadEntry* entry = ThreadEntry::AddThreadToUnwind(
      thread_intf_, Pid(), Tid(), num_ignore_frames);
  if (!entry) {
    return false;
  }

  // Prevent multiple threads trying to set the trigger action on different
  // threads at the same time.
  bool retval = false;
  if (pthread_mutex_lock(&g_sigaction_mutex) == 0) {
    struct sigaction act, oldact;
    memset(&act, 0, sizeof(act));
    act.sa_sigaction = SignalHandler;
    act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
    sigemptyset(&act.sa_mask);
    if (sigaction(SIGURG, &act, &oldact) == 0) {
      retval = TriggerUnwindOnThread(entry);
      sigaction(SIGURG, &oldact, NULL);
    } else {
      BACK_LOGW("sigaction failed %s", strerror(errno));
    }
    pthread_mutex_unlock(&g_sigaction_mutex);
  } else {
    BACK_LOGW("unable to acquire sigaction mutex.");
  }

  if (retval) {
    FinishUnwind();
  }
  delete entry;

  return retval;
}
