github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/cmd/scandeps/server/server.cc (about)

     1  // Copyright 2023 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  #include "server.h"
    16  
    17  #ifdef _WIN32
    18  #define GLOG_NO_ABBREVIATED_SEVERITIES
    19  #endif
    20  #include <glog/logging.h>
    21  #include <grpcpp/grpcpp.h>
    22  
    23  #include <thread>
    24  
    25  #include "api/scandeps/cppscandeps.grpc.pb.h"
    26  #include "scandeps.h"
    27  
    28  using scandeps::CPPDepsScanner;
    29  using scandeps::CPPProcessInputsRequest;
    30  using scandeps::CPPProcessInputsResponse;
    31  using scandeps::StatusResponse;
    32  
    33  // Argument to start_server
    34  typedef struct ScandepsServerWrapper {
    35    grpc::Server *grpc_server;
    36    bool *running;
    37    std::condition_variable *shutdown_condition;
    38    std::mutex *shutdown_mutex;
    39    uint32_t *shutdown_delay_seconds;
    40  } ScandepsServerWrapper;
    41  
    42  void *StartServer(void *server) {
    43    ScandepsServerWrapper *tserver = (ScandepsServerWrapper *)(server);
    44    std::unique_lock<std::mutex> shutdown_lock(*(tserver->shutdown_mutex));
    45    *(tserver->running) = true;
    46    tserver->shutdown_condition->wait(
    47        shutdown_lock, [tserver]() { return !(*(tserver->running)); });
    48    LOG(INFO) << "Stopping server.";
    49    auto deadline = std::chrono::system_clock::now() +
    50                    std::chrono::seconds(*(tserver->shutdown_delay_seconds));
    51    tserver->grpc_server->Shutdown(deadline);
    52    return NULL;
    53  }
    54  
    55  ScandepsServer::ScandepsServer(const std::string &server_address,
    56                                 const std::string &cache_dir,
    57                                 const std::string &log_dir,
    58                                 int cache_size_max_mb, bool use_deps_cache,
    59                                 uint32_t shutdown_delay_seconds,
    60                                 uint32_t experimental_deadlock,
    61                                 uint32_t experimental_segfault)
    62      : running_(false),
    63        server_address_(server_address),
    64        cache_dir_(cache_dir),
    65        log_dir_(log_dir),
    66        cache_size_max_mb_(cache_size_max_mb),
    67        use_deps_cache_(use_deps_cache),
    68        shutdown_delay_seconds_(shutdown_delay_seconds),
    69        experimental_deadlock_(experimental_deadlock),
    70        experimental_segfault_(experimental_segfault) {}
    71  
    72  ScandepsServer::~ScandepsServer() {}
    73  
    74  bool ScandepsServer::RunServer(const char *process_name) {
    75    scandeps::CPPDepsScanner::Service *service = newDepsScanner(
    76        [&]() { this->StopServer(); }, process_name, cache_dir_.c_str(),
    77        log_dir_.c_str(), cache_size_max_mb_, use_deps_cache_,
    78        experimental_deadlock_, experimental_segfault_);
    79  
    80    grpc::ServerBuilder builder;
    81    // Listen on the given address without any authentication mechanism.
    82    builder.AddListeningPort(server_address_, grpc::InsecureServerCredentials());
    83    builder.RegisterService(service);
    84    grpc_server_ = builder.BuildAndStart();
    85    if (grpc_server_ == nullptr) {
    86      LOG(ERROR) << "Failed to bind to address " << server_address_;
    87      return false;
    88    }
    89    LOG(INFO) << "Server listening on " << server_address_;
    90    google::FlushLogFiles(0);
    91  
    92  #if !defined(__linux__) || __GLIBC_NEW__
    93    // Use C++ threads
    94    std::thread run_thread = std::thread([&]() {
    95      std::unique_lock<std::mutex> shutdown_lock(shutdown_mutex_);
    96      running_ = true;
    97      shutdown_condition_.wait(shutdown_lock, [this]() { return !running_; });
    98      LOG(INFO) << "Stopping server.";
    99      auto deadline = std::chrono::system_clock::now() +
   100                      std::chrono::seconds(shutdown_delay_seconds_);
   101      grpc_server_->Shutdown(deadline);
   102    });
   103    grpc_server_->Wait();
   104    run_thread.join();
   105  #else
   106    // Must use pthread for 1604 compatibility
   107    ScandepsServerWrapper tserver;
   108    tserver.grpc_server = grpc_server_.get();
   109    tserver.running = &running_;
   110    tserver.shutdown_condition = &shutdown_condition_;
   111    tserver.shutdown_mutex = &shutdown_mutex_;
   112    tserver.shutdown_delay_seconds = &shutdown_delay_seconds_;
   113  
   114    pthread_t run_thread;
   115    int tret = pthread_create(&run_thread, NULL, StartServer, (void *)&tserver);
   116    if (tret != 0) {
   117      LOG(ERROR) << "Failed to start server thread; aborting.";
   118      grpc_server_->Shutdown();
   119    } else {
   120      grpc_server_->Wait();
   121      pthread_join(run_thread, NULL);
   122    }
   123  #endif
   124    LOG(INFO) << "Server stopped, destroying deps scanner.";
   125    deleteDepsScanner(service);
   126    return true;
   127  }
   128  
   129  void ScandepsServer::StopServer() {
   130    if (running_) {
   131      std::lock_guard<std::mutex> shutdown_lock(shutdown_mutex_);
   132      running_ = false;
   133      shutdown_condition_.notify_all();
   134    }
   135  }