コード例 #1
0
Array c_WaitableWaitHandle::t_getdependencystack() {
  Array result = Array::Create();
  if (isFinished()) return result;
  hphp_hash_set<int64_t> visited;
  auto wait_handle = this;
  auto session = AsioSession::Get();
  while (wait_handle != nullptr) {
    result.append(wait_handle);
    visited.insert(wait_handle->t_getid());
    auto context_idx = wait_handle->getContextIdx();

    // 1. find parent in the same context
    auto p = wait_handle->getParentChain().firstInContext(context_idx);
    if (p && visited.find(p->t_getid()) == visited.end()) {
      wait_handle = p;
      continue;
    }

    // 2. cross the context boundary
    auto context = session->getContext(context_idx);
    if (!context) {
      break;
    }
    wait_handle = c_ResumableWaitHandle::getRunning(context->getSavedFP());
    auto target_context_idx = wait_handle ? wait_handle->getContextIdx() : 0;
    while (context_idx > target_context_idx) {
      --context_idx;
      result.append(null_object);
    }
  }
  return result;
}
コード例 #2
0
Array c_WaitableWaitHandle::t_getdependencystack() {
  Array result = Array::Create();
  if (isFinished()) return result;
  hphp_hash_set<int64_t> visited;
  auto wait_handle = this;
  while (wait_handle != nullptr) {
    result.append(wait_handle);
    visited.insert(wait_handle->t_getid());
    auto context_idx = wait_handle->getContextIdx();

    // 1. find parent in the same context
    auto p = wait_handle->getFirstParent();
    while (p) {
      if ((p->getContextIdx() == context_idx) &&
          visited.find(p->t_getid()) == visited.end()) {
        wait_handle = p;
        break;
      }
      p = p->getNextParent();
    }
    if (p) continue;

    // 2. cross the context boundary
    result.append(null_object);
    wait_handle = (context_idx > 1)
      ? AsioSession::Get()->getContext(context_idx - 1)->getCurrent()
      : nullptr;
  }
  return result;
}
コード例 #3
0
ファイル: cmd_where.cpp プロジェクト: stone54321277/hhvm
// Form a trace of the async stack starting with the currently running
// generator, if any. For now we just toss in the function name and
// id, as well as the pseudo-frames for context breaks at explicit
// joins. Later we'll add more, like file and line, hopefully function
// args, wait handle status, etc.
static Array createAsyncStacktrace() {
  Array trace;
  auto currentWaitHandle = HHVM_FN(asio_get_running)();
  if (currentWaitHandle.isNull()) return trace;
  Array depStack =
    objToWaitableWaitHandle(currentWaitHandle)->t_getdependencystack();
  for (ArrayIter iter(depStack); iter; ++iter) {
    if (iter.secondRef().isNull()) {
      trace.append(Array(staticEmptyArray()));
    } else {
      auto wh = objToWaitableWaitHandle(iter.secondRef().toObject());
      auto parents = wh->t_getparents();
      Array ancestors;
      for (ArrayIter piter(parents); piter; ++piter) {
        // Note: the parent list contains no nulls.
        auto parent = objToWaitableWaitHandle(piter.secondRef().toObject());
        ancestors.append(parent->t_getname());
      }
      Array frameData;
      frameData.set(s_function, wh->t_getname(), true);
      frameData.set(s_id, wh->t_getid(), true);
      frameData.set(s_ancestors, ancestors, true);
      // Async function wait handles may have a source location to add.
      if (wh->getKind() == c_WaitHandle::Kind::AsyncFunction) {
        auto afwh = static_cast<c_AsyncFunctionWaitHandle*>(wh);
        addAsyncFunctionLocation(frameData, *afwh);
      }
      trace.append(frameData);
    }
  }
  return trace;
}
コード例 #4
0
// always throws
void c_BlockableWaitHandle::reportCycle(c_WaitableWaitHandle* start) {
  assert(getState() == STATE_BLOCKED);
  assert(getChild() == start);

  smart::vector<std::string> exception_msg_items;
  exception_msg_items.push_back("Encountered dependency cycle.\n");
  exception_msg_items.push_back("Existing stack:\n");

  assert(dynamic_cast<c_BlockableWaitHandle*>(start));
  auto current = static_cast<c_BlockableWaitHandle*>(start);
  assert(current->getState() == STATE_BLOCKED);

  do {
    exception_msg_items.push_back(folly::stringPrintf(
        "  %s (%" PRId64 ")\n", current->getName()->data(), current->t_getid()));

    auto next = current->getChild();
    assert(dynamic_cast<c_BlockableWaitHandle*>(next));
    current = static_cast<c_BlockableWaitHandle*>(next);
    assert(current->getState() == STATE_BLOCKED);
  } while (current != start);

  exception_msg_items.push_back("Trying to introduce dependency on:\n");
  exception_msg_items.push_back(folly::stringPrintf(
      "  %s (%" PRId64 ") (dupe)\n", start->getName()->data(), start->t_getid()));
  Object e(SystemLib::AllocInvalidOperationExceptionObject(
      folly::join("", exception_msg_items)));
  throw e;
}
コード例 #5
0
ObjectData*
c_BlockableWaitHandle::createCycleException(c_WaitableWaitHandle* child) const {
  assert(isDescendantOf(child));

  smart::vector<std::string> exception_msg_items;
  exception_msg_items.push_back("Encountered dependency cycle.\n");
  exception_msg_items.push_back("Existing stack:\n");

  exception_msg_items.push_back(folly::stringPrintf(
    "  %s (%" PRId64 ")\n", child->getName().data(), child->t_getid()));

  assert(child->instanceof(c_BlockableWaitHandle::classof()));
  auto current = static_cast<c_BlockableWaitHandle*>(child);

  while (current != this) {
    assert(current->getState() == STATE_BLOCKED);
    assert(current->getChild()->instanceof(c_BlockableWaitHandle::classof()));
    current = static_cast<c_BlockableWaitHandle*>(current->getChild());

    exception_msg_items.push_back(folly::stringPrintf(
      "  %s (%" PRId64 ")\n", current->getName().data(), current->t_getid()));
  }

  exception_msg_items.push_back("Trying to introduce dependency on:\n");
  exception_msg_items.push_back(folly::stringPrintf(
    "  %s (%" PRId64 ") (dupe)\n", child->getName().data(), child->t_getid()));
  return SystemLib::AllocInvalidOperationExceptionObject(
      folly::join("", exception_msg_items));
}
コード例 #6
0
ファイル: cmd_where.cpp プロジェクト: 360buyliulei/hiphop-php
// Form a trace of the async stack starting with the currently running
// generator, if any. For now we just toss in the function name and
// id, as well as the pseudo-frames for context breaks at explicit
// joins. Later we'll add more, like file and line, hopefully function
// args, wait handle status, etc.
Array createAsyncStacktrace() {
  Array trace;
  auto currentWaitHandle = f_asio_get_running();
  if (currentWaitHandle.isNull()) return trace;
  Array depStack =
    objToWaitableWaitHandle(currentWaitHandle)->t_getdependencystack();
  for (ArrayIter iter(depStack); iter; ++iter) {
    if (iter.secondRef().isNull()) {
      trace.append(ArrayInit(0).toVariant());
    } else {
      auto wh = objToWaitableWaitHandle(iter.secondRef().toObject());
      auto parents = wh->t_getparents();
      Array ancestors;
      for (ArrayIter piter(parents); piter; ++piter) {
        // Note: the parent list contains no nulls.
        auto parent = objToWaitableWaitHandle(piter.secondRef().toObject());
        ancestors.append(parent->t_getname());
      }
      Array frameData;
      frameData.set(s_function, wh->t_getname(), true);
      frameData.set(s_id, wh->t_getid(), true);
      frameData.set(s_ancestors, ancestors, true);
      // Continuation wait handles may have a source location to add.
      auto contWh = dynamic_cast<c_AsyncFunctionWaitHandle*>(wh);
      if (contWh != nullptr) addContinuationLocation(frameData, *contWh);
      trace.append(frameData);
    }
  }
  return trace;
}