1 /* 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <inttypes.h> 18 #include <limits.h> 19 #include <stdio.h> 20 #include <stdint.h> 21 #include <stdlib.h> 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 #include <sys/wait.h> 25 #include <fcntl.h> 26 #include <unistd.h> 27 #include <signal.h> 28 29 #include <algorithm> 30 #include <cstdlib> 31 #include <fstream> 32 #include <iomanip> 33 #include <memory> 34 #include <sstream> 35 #include <string> 36 #include <vector> 37 38 #include <gflags/gflags.h> 39 #include <glog/logging.h> 40 41 #include "common/libs/fs/shared_fd.h" 42 #include "common/libs/fs/shared_select.h" 43 #include "common/libs/utils/environment.h" 44 #include "host/commands/launch/launcher_defs.h" 45 #include "host/libs/config/cuttlefish_config.h" 46 #include "host/libs/vm_manager/vm_manager.h" 47 48 DEFINE_int32(wait_for_launcher, 5, 49 "How many seconds to wait for the launcher to respond to the stop " 50 "command. A value of zero means wait indefinetly"); 51 52 namespace { 53 // Gets a set of the possible process groups of a previous launch 54 std::set<pid_t> GetCandidateProcessGroups() { 55 std::string cmd = "fuser"; 56 // Add the instance directory 57 cmd += " " + cvd::StringFromEnv("HOME", ".") + "/cuttlefish_runtime/*"; 58 // Add the shared memory file 59 cmd += " " + vsoc::GetPerInstanceDefault("/dev/shm/cvd-"); 60 std::shared_ptr<FILE> cmd_out(popen(cmd.c_str(), "r"), pclose); 61 if (!cmd_out) { 62 LOG(ERROR) << "Unable to execute '" << cmd << "': " << strerror(errno); 63 return {}; 64 } 65 int64_t pid; 66 std::set<pid_t> ret{}; 67 while(fscanf(cmd_out.get(), "%" PRId64, &pid) != EOF) { 68 pid_t pgid = getpgid(static_cast<pid_t>(pid)); 69 if (pgid < 0) { 70 LOG(ERROR) << "Unable to get process group of " << pid << ": " 71 << strerror(errno); 72 continue; 73 } 74 ret.insert(pgid); 75 } 76 // The process group of stop_cvd should not be killed 77 ret.erase(getpgrp()); 78 return ret; 79 } 80 81 int FallBackStop() { 82 auto exit_code = 1; // Having to fallback is an error 83 84 auto process_groups = GetCandidateProcessGroups(); 85 for (auto pgid: process_groups) { 86 LOG(INFO) << "Sending SIGKILL to process group " << pgid; 87 auto retval = killpg(pgid, SIGKILL); 88 if (retval < 0) { 89 LOG(ERROR) << "Failed to kill process group " << pgid << ": " 90 << strerror(errno); 91 exit_code |= 4; 92 } 93 } 94 95 return exit_code; 96 } 97 } // anonymous namespace 98 99 int main(int argc, char** argv) { 100 ::android::base::InitLogging(argv, android::base::StderrLogger); 101 google::ParseCommandLineFlags(&argc, &argv, true); 102 103 auto config = vsoc::CuttlefishConfig::Get(); 104 if (!config) { 105 LOG(ERROR) << "Failed to obtain config object"; 106 return FallBackStop(); 107 } 108 109 auto monitor_path = config->launcher_monitor_socket_path(); 110 if (monitor_path.empty()) { 111 LOG(ERROR) << "No path to launcher monitor found"; 112 return FallBackStop(); 113 } 114 auto monitor_socket = cvd::SharedFD::SocketLocalClient(monitor_path.c_str(), 115 false, SOCK_STREAM); 116 if (!monitor_socket->IsOpen()) { 117 LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path 118 << ": " << monitor_socket->StrError(); 119 return FallBackStop(); 120 } 121 auto request = cvd::LauncherAction::kStop; 122 auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0); 123 if (bytes_sent < 0) { 124 LOG(ERROR) << "Error sending launcher monitor the stop command: " 125 << monitor_socket->StrError(); 126 return FallBackStop(); 127 } 128 // Perform a select with a timeout to guard against launcher hanging 129 cvd::SharedFDSet read_set; 130 read_set.Set(monitor_socket); 131 struct timeval timeout = {FLAGS_wait_for_launcher, 0}; 132 int selected = cvd::Select(&read_set, nullptr, nullptr, 133 FLAGS_wait_for_launcher <= 0 ? nullptr : &timeout); 134 if (selected < 0){ 135 LOG(ERROR) << "Failed communication with the launcher monitor: " 136 << strerror(errno); 137 return FallBackStop(); 138 } 139 if (selected == 0) { 140 LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond"; 141 return FallBackStop(); 142 } 143 cvd::LauncherResponse response; 144 auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0); 145 if (bytes_recv < 0) { 146 LOG(ERROR) << "Error receiving response from launcher monitor: " 147 << monitor_socket->StrError(); 148 return FallBackStop(); 149 } 150 if (response != cvd::LauncherResponse::kSuccess) { 151 LOG(ERROR) << "Received '" << static_cast<char>(response) 152 << "' response from launcher monitor"; 153 return FallBackStop(); 154 } 155 LOG(INFO) << "Successfully stopped device"; 156 return 0; 157 } 158