[clang] [llvm] [clang][MBD] set up module build daemon infrastructure (PR #67562)

Connor Sughrue via cfe-commits cfe-commits at lists.llvm.org
Wed Apr 17 13:46:28 PDT 2024


================
@@ -0,0 +1,157 @@
+//===---------------------------- Frontend.cpp ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/ModuleBuildDaemon/Frontend.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Tooling/ModuleBuildDaemon/SocketSupport.h"
+#include "clang/Tooling/ModuleBuildDaemon/Utils.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ExponentialBackoff.h"
+#include "llvm/Support/Program.h"
+
+#include <cerrno>
+#include <chrono>
+#include <filesystem>
+#include <fstream>
+#include <optional>
+#include <string>
+#include <thread>
+
+using namespace llvm;
+
+namespace clang::tooling::cc1modbuildd {
+
+llvm::Error attemptHandshake(raw_socket_stream &Client,
+                             DiagnosticsEngine &Diag) {
+
+  // Send HandshakeMsg to module build daemon
+  HandshakeMsg Request{ActionType::HANDSHAKE, StatusType::REQUEST};
+  if (llvm::Error Err = writeMsgStructToSocket(Client, Request))
+    return Err;
+
+  // Read response from module build daemon
+  Expected<HandshakeMsg> MaybeResponse =
+      readMsgStructFromSocket<HandshakeMsg>(Client);
+  if (!MaybeResponse) {
+    return MaybeResponse.takeError();
+  }
+  HandshakeMsg Response = std::move(*MaybeResponse);
+
+  assert(Response.MsgAction == ActionType::HANDSHAKE &&
+         "The response ActionType should only ever be HANDSHAKE");
+
+  if (Response.MsgStatus == StatusType::SUCCESS) {
+    return llvm::Error::success();
+  }
+
+  return llvm::make_error<StringError>(
+      "Received handshake response 'FAILURE' from module build daemon",
+      std::make_error_code(std::errc::operation_not_permitted));
+}
+
+llvm::Error spawnModuleBuildDaemon(const CompilerInvocation &Clang,
+                                   const char *Argv0, DiagnosticsEngine &Diag,
+                                   std::string BasePath) {
+
+  std::vector<StringRef> Args = {Argv0, ModuleBuildDaemonFlag};
+  if (!Clang.getFrontendOpts().ModuleBuildDaemonPath.empty())
+    Args.push_back(BasePath.c_str());
+
+  std::string ErrorBuffer;
+  llvm::sys::ExecuteNoWait(Argv0, Args, std::nullopt, {}, 0, &ErrorBuffer,
+                           nullptr, nullptr, /*DetachProcess*/ true);
+
+  // llvm::sys::ExecuteNoWait can fail for a variety of reasons which can't be
+  // generalized to one error code
+  if (!ErrorBuffer.empty())
+    return llvm::make_error<StringError>(ErrorBuffer, inconvertibleErrorCode());
+
+  Diag.Report(diag::remark_mbd_spawn);
+  return llvm::Error::success();
+}
+
+Expected<std::unique_ptr<raw_socket_stream>>
+getModuleBuildDaemon(const CompilerInvocation &Clang, const char *Argv0,
+                     DiagnosticsEngine &Diag, StringRef BasePath) {
+
+  SmallString<128> SocketPath = BasePath;
+  llvm::sys::path::append(SocketPath, SocketFileName);
+
+  if (llvm::sys::fs::exists(SocketPath)) {
+    Expected<std::unique_ptr<raw_socket_stream>> MaybeClient =
+        raw_socket_stream::createConnectedUnix(SocketPath);
+    if (MaybeClient)
+      return std::move(*MaybeClient);
+    consumeError(MaybeClient.takeError());
+  }
+
+  if (llvm::Error Err =
+          spawnModuleBuildDaemon(Clang, Argv0, Diag, BasePath.str()))
+    return std::move(Err);
+
+  std::chrono::seconds MaxWaitTime(30);
+  ExponentialBackoff Backoff(MaxWaitTime);
+  do {
+    if (llvm::sys::fs::exists(SocketPath)) {
+      Expected<std::unique_ptr<raw_socket_stream>> MaybeClient =
+          raw_socket_stream::createConnectedUnix(SocketPath);
+      if (MaybeClient) {
+        Diag.Report(diag::remark_mbd_connection) << SocketPath;
+        return std::move(*MaybeClient);
+      }
+      consumeError(MaybeClient.takeError());
+    }
+  } while (Backoff.waitForNextAttempt());
+
+  // After waiting around 30 seconds give up and return an error
+  return llvm::make_error<StringError>(
+      "Max wait time exceeded: ",
----------------
cpsughrue wrote:

Remove ": "

https://github.com/llvm/llvm-project/pull/67562


More information about the cfe-commits mailing list