예제 #1
0
void preloadRepo() {
  auto& repo = Repo::get();
  auto units = repo.enumerateUnits(RepoIdLocal, true, false);
  if (units.size() == 0) {
    units = repo.enumerateUnits(RepoIdCentral, true, false);
  }
  if (!units.size()) return;

  std::vector<std::thread> workers;
  auto numWorkers = Process::GetCPUCount();
  // Compute a batch size that causes each thread to process approximately 16
  // batches.  Even if the batches are somewhat imbalanced in what they contain,
  // the straggler workers are very unlikey to take more than 10% longer than
  // the first worker to finish.
  size_t batchSize{std::max(units.size() / numWorkers / 16, size_t(1))};
  std::atomic<size_t> index{0};
  for (auto worker = 0; worker < numWorkers; ++worker) {
    workers.push_back(std::thread([&] {
      hphp_session_init();
      hphp_context_init();

      while (true) {
        auto begin = index.fetch_add(batchSize);
        auto end = std::min(begin + batchSize, units.size());
        if (begin >= end) break;
        auto unitCount = end - begin;
        for (auto i = size_t{0}; i < unitCount; ++i) {
          auto& kv = units[begin + i];
          try {
            lookupUnit(String(RuntimeOption::SourceRoot + kv.first).get(),
                       "", nullptr);
          } catch (...) {
            // swallow errors silently
          }
        }
      }

      hphp_context_exit();
      hphp_session_exit();
      hphp_thread_exit();

    }));
  }
  for (auto& worker : workers) {
    worker.join();
  }
}
예제 #2
0
파일: ext_hh.cpp 프로젝트: aloiret/hhvm
bool HHVM_FUNCTION(could_include, const String& file) {
  return lookupUnit(file.get(), "", nullptr /* initial_opt */) != nullptr;
}
예제 #3
0
bool RunToLocationCommand::executeImpl(DebuggerSession* session,
                                       folly::dynamic* /*responseMsg*/
) {
  folly::dynamic& message = getMessage();
  const folly::dynamic& args = tryGetObject(message, "arguments", s_emptyArgs);
  const folly::dynamic& source = tryGetObject(args, "source", s_emptyArgs);
  const std::string& filePath = tryGetString(source, "path", "");

  if (filePath.empty()) {
    throw DebuggerCommandException(
      "Run to location source path not specified."
    );
  }

  const ClientPreferences& prefs = m_debugger->getClientPreferences();
  const std::string& path = File::TranslatePath(String(filePath)).toCppString();
  BreakpointManager* bpMgr = session->getBreakpointManager();

  int line = tryGetInt(args, "line", -1);
  if (!prefs.linesStartAt1) {
    // If client lines start at 0, make them 1 based.
    line++;
  }

  if (line <= 0) {
    throw DebuggerCommandException(
      "Invalid continue to line specified."
    );
  }

  // See if there's already a breakpoint at this file + line.
  const auto bpIds = bpMgr->getBreakpointIdsByFile(path);
  for (auto it = bpIds.begin(); it != bpIds.end(); it++) {
    Breakpoint* bp = bpMgr->getBreakpointById(*it);
    if (bp->m_line == line) {
      // There's already a breakpoint installed at the run to location.
      // Just resume the request thread and let it hit.
      return true;
    }
  }

  // Find a compilation unit to place a temp bp in.
  HPHP::String unitPath(path.c_str());
  const auto compilationUnit = lookupUnit(unitPath.get(), "", nullptr);
  if (compilationUnit == nullptr) {
    throw DebuggerCommandException(
      "Could not find a loaded compilation unit to run to location in!"
    );
  }

  std::pair<int, int> runLocation =
    m_debugger->calibrateBreakpointLineInUnit(compilationUnit, line);

  if (runLocation.first < 0) {
    throw DebuggerCommandException(
      "Could not find a suitable location in the compilation unit to run to!"
    );
  }

  if (!phpAddBreakPointLine(compilationUnit, runLocation.first)) {
    throw DebuggerCommandException(
      "Failed to install temporary breakpoint at location."
    );
  }

  RequestInfo* ri = m_debugger->getRequestInfo();
  ri->m_runToLocationInfo.path = path;
  ri->m_runToLocationInfo.line = line;

  // Tell the user where we're running to. Resolving the file path and
  // calibrating the source line could have modified things a bit.
  std::string userMsg = "Resuming request ";
  userMsg += std::to_string(targetThreadId(session));
  userMsg += " and running to resolved location ";
  userMsg += path;
  userMsg += ":";
  userMsg += std::to_string(runLocation.second);
  m_debugger->sendUserMessage(userMsg.c_str(), DebugTransport::OutputLevelInfo);

  // Resume only this request thread.
  return true;
}
예제 #4
0
 // (PHP-CALLBACK entry-point) This manually gets a lock where needed but
 // avoids holding one most of the time as this can be a quite slow operation.
 void runCallback() {
   hphp_session_init(Treadmill::SessionKind::Watchman);
   auto context = g_context.getNoCheck();
   SCOPE_EXIT {
     hphp_context_exit();
     hphp_session_exit();
     {
       std::lock_guard<std::mutex> g(s_sharedDataMutex);
       processNextUpdate();
     }
   };
   try {
     std::string json_data;
     {
       std::lock_guard<std::mutex> g(s_sharedDataMutex);
       if (m_unprocessedCallbackData.empty()) {
         return;
       }
       auto& data = m_unprocessedCallbackData.back();
       json_data = toJson(data);
       m_unprocessedCallbackData.pop_back();
     }
     bool initial;
     auto unit = lookupUnit(
       String(m_callbackFile.c_str()).get(),
       "",
       &initial,
       Native::s_noNativeFuncs);
     if (!unit) {
       throw std::runtime_error(
         folly::sformat("Unit '{}' no longer exists.", m_callbackFile));
     }
     auto unit_result = Variant::attach(context->invokeUnit(unit));
     auto func = Unit::loadFunc(String(m_callbackFunc.c_str()).get());
     if (!func) {
       throw std::runtime_error(
         folly::sformat("Callback '{}' no longer exists", m_callbackFunc));
     }
     String str_path(m_path.c_str());
     String str_query(m_query.c_str());
     String str_name(m_name.c_str());
     String str_json_data(json_data.c_str());
     String str_socket_path(m_socketPath.c_str());
     TypedValue args[] = {
       str_path.toCell(),
       str_query.toCell(),
       str_name.toCell(),
       str_json_data.toCell(),
       str_socket_path.toCell(),
     };
     tvDecRefGen(
         context->invokeFuncFew(func,
                                nullptr, // thisOrCls
                                nullptr, // invName
                                5, // argc
                                args)
     );
   } catch(Exception& e) {
     if (m_error.empty()) {
       m_error = e.getMessage();
     }
   } catch(Object& e) {
     if (m_error.empty()) {
       try {
         m_error = e->invokeToString().data();
       } catch(...) {
         m_error = "PHP exception which cannot be turned into a string";
       }
     }
   } catch(const std::exception& e) {
     if (m_error.empty()) {
       m_error = folly::exceptionStr(e).toStdString();
     }
   } catch(...) {
     if (m_error.empty()) {
       m_error = "Unknown error (non std::exception)";
     }
   }
 }