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 }