Example #1
0
void XDebugServer::addCmdAndTrans(xdebug_xml_node& node) {
  // lastcmd and lasttransid are not always set (for example when the
  // connection is severed before the first command is sent)
  if (m_lastCommand == Command::NONE || m_lastTransactionId == nullptr) {
    return;
  }

  // TODO(#4489053) Change this when xml api is changed
  char* command = const_cast<char*>(getCommandStr(m_lastCommand));
  xdebug_xml_add_attribute_ex(&node, "command", command, 0, 0);
  xdebug_xml_add_attribute_ex(&node, "transaction_id",
                              m_lastTransactionId, 0, 0);
}
Example #2
0
void XDebugHook::onOpcode(PC pc) {
  auto server = XDEBUG_GLOBAL(Server);
  if (server == nullptr) {
    return;
  }

  // Likely case is that there was no break command.
  auto brk = server->getAndClearBreak();
  if (LIKELY(brk == nullptr)) {
    return;
  }

  server->log("Request thread received break command");

  VMRegAnchor anchor;

  auto const unit = vmfp()->func()->unit();
  auto const line = unit->getLineNumber(unit->offsetOf(pc));
  auto const filepath = const_cast<StringData*>(unit->filepath());
  auto const transpath = File::TranslatePath(String(filepath));

  // XDebugServer::breakpoint will send the response for the command before the
  // break command, but we first need to send a response for the break command.
  auto response = xdebug_xml_node_init("response");
  server->addXmlns(*response);

  auto const& cmd_str  = brk->getCommandStr();
  auto const& trans_id = brk->getTransactionId();

  // Manually add status and reason.  XDebugServer still thinks we're running
  // because we haven't run XDebugServer::breakpoint yet.
  xdebug_xml_add_attribute(response, "status", "break");
  xdebug_xml_add_attribute(response, "reason", "ok");

  // Ditto with command, XDebugServer is tracking the command before the break.
  xdebug_xml_add_attribute_dup(response, "command", cmd_str.data());
  xdebug_xml_add_attribute_dup(response, "transaction_id", trans_id.data());

  delete brk;

  server->sendMessage(*response);
  xdebug_xml_node_dtor(response);

  // Now we can go into a command loop.
  server->breakpoint(transpath, init_null(), init_null(), line);
}
Example #3
0
void XDebugServer::pollSocketLoop() {
  while (true) {
    // Take some load off the CPU when polling thread is paused.
    std::this_thread::sleep_for(std::chrono::seconds(1));

    // XXX: This can take the lock even when we want to pause the thread.
    std::lock_guard<std::mutex> lock(m_pollingMtx);

    // We're paused if the request thread is handling commands right now.
    if (m_pausePollingThread.load()) {
      continue;
    }

    // We've been told to exit.
    if (m_stopPollingThread.load()) {
      log("Polling thread stopping\n");
      break;
    }

    // At this point we know that the request thread is busy running, so we let
    // it enter the jit.
    m_requestThread->m_reqInjectionData.setDebuggerIntr(false);

    if (m_bufferAvail == 0) {
      // Check if there is any input waiting on us.
      if (!poll_socket(m_socket)) {
        continue;
      }

      // Actually get the input from the socket.
      if (!readInput()) {
        log("Polling thread had input but failed to read it\n");
        continue;
      }
    }

    try {
      log("Polling thread received: %s\n", m_bufferCur);
      auto cmd = parseCommand();
      if (cmd->getCommandStr() != "break") {
        delete cmd;
        continue;
      }

      log("Received break command\n");

      // We're going to set the 'break' flag on our XDebugServer, and pause
      // ourselves.  The request thread will unpause us when it exits its
      // command loop.
      m_pausePollingThread.store(true);

      auto const old = m_break.exchange(cmd);
      always_assert(old == nullptr);

      // Force request thread to run in the interpreter, and hit
      // XDebugHookHandler::onOpcode().
      m_requestThread->m_reqInjectionData.setDebuggerIntr(true);
      m_requestThread->m_reqInjectionData.setFlag(DebuggerSignalFlag);
    } catch (const XDebugExn&) {
      log("Polling thread got invalid command: %s\n", m_bufferCur);
      // Can drop the error.
    }
  }
}