[clang] [llvm] [clang][MBD] set up module build daemon infrastructure (PR #67562)
Michael Spencer via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 17 14:20:15 PDT 2024
================
@@ -0,0 +1,289 @@
+//===------- cc1modbuildd_main.cpp - Clang CC1 Module Build Daemon --------===//
+//
+// 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/SocketSupport.h"
+#include "clang/Tooling/ModuleBuildDaemon/Utils.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/ThreadPool.h"
+
+#include <csignal>
+#include <cstdbool>
+#include <cstdio>
+#include <cstring>
+#include <fstream>
+#include <optional>
+#include <string>
+#include <system_error>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
+using namespace llvm;
+using namespace clang::tooling::cc1modbuildd;
+
+// Create unbuffered STDOUT stream so that any logging done by the module build
+// daemon can be viewed without having to terminate the process
+static raw_fd_ostream &unbuff_outs() {
+ static raw_fd_ostream S(fileno(stdout), false, true);
+ return S;
+}
+
+static bool LogVerbose = false;
+static void logVerbose(const llvm::Twine &message) {
+ if (LogVerbose) {
+ unbuff_outs() << message << '\n';
+ }
+}
+
+static void modifySignals(decltype(SIG_DFL) handler) {
+
+ if (std::signal(SIGTERM, handler) == SIG_ERR) {
+ errs() << "failed to handle SIGTERM" << '\n';
+ exit(EXIT_FAILURE);
+ }
+
+ if (std::signal(SIGINT, handler) == SIG_ERR) {
+ errs() << "failed to handle SIGINT" << '\n';
+ exit(EXIT_FAILURE);
+ }
+
+#ifdef SIGHUP
+ if (::signal(SIGHUP, SIG_IGN) == SIG_ERR) {
+ errs() << "failed to handle SIGHUP" << '\n';
+ exit(EXIT_FAILURE);
+ }
+#endif
+}
+
+namespace {
+
+class ModuleBuildDaemonServer {
+public:
+ SmallString<256> SocketPath;
+ SmallString<256> Stderr; // path to stderr
+ SmallString<256> Stdout; // path to stdout
+
+ explicit ModuleBuildDaemonServer(StringRef Path)
+ : SocketPath(Path), Stderr(Path), Stdout(Path) {
+ llvm::sys::path::append(SocketPath, SocketFileName);
+ llvm::sys::path::append(Stdout, StdoutFileName);
+ llvm::sys::path::append(Stderr, StderrFileName);
+ }
+
+ void setupDaemonEnv();
+ void createDaemonSocket();
+ void listenForClients();
+
+ static void handleConnection(std::shared_ptr<raw_socket_stream> Connection);
+
+ // TODO: modify so when shutdownDaemon is called the daemon stops accepting
+ // new client connections and waits for all existing client connections to
+ // terminate before closing the file descriptor and exiting
+ void shutdownDaemon() {
+ RunServiceLoop = false;
+ if (ServerListener.has_value())
+ ServerListener.value().shutdown();
+ }
+
+private:
+ std::atomic<bool> RunServiceLoop = true;
+ std::optional<llvm::ListeningSocket> ServerListener;
----------------
Bigcheese wrote:
This is set after the signal handler is installed so it needs to be atomic.
```suggestion
std::atomic<llvm::ListeningSocket *> ServerListener;
std::optional<llvm::ListeningSocket> ServerListenerStorage;
```
Then in `createDaemonSocket ` set `ServerListener = &*ServerListenerStorage`, and in `shutdownDaemon` use the `ServerListener` atomic pointer instead of the optional.
In the case that shutdown is called before the `ServerListener` is set, the server will still shutdown because `RunServiceLoop` will be false and `accept` will never be called.
https://github.com/llvm/llvm-project/pull/67562
More information about the cfe-commits
mailing list