Home | History | Annotate | Download | only in launch
      1 /*
      2  * Copyright (C) 2017 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 <limits.h>
     18 #include <signal.h>
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 #include <sys/types.h>
     22 #include <sys/stat.h>
     23 #include <sys/wait.h>
     24 #include <fcntl.h>
     25 #include <unistd.h>
     26 
     27 #include <algorithm>
     28 #include <functional>
     29 #include <iostream>
     30 #include <fstream>
     31 #include <iomanip>
     32 #include <memory>
     33 #include <sstream>
     34 #include <string>
     35 #include <thread>
     36 #include <vector>
     37 
     38 #include <gflags/gflags.h>
     39 #include <glog/logging.h>
     40 #include <host/libs/vm_manager/crosvm_manager.h>
     41 
     42 #include "common/libs/fs/shared_fd.h"
     43 #include "common/libs/fs/shared_select.h"
     44 #include "common/libs/strings/str_split.h"
     45 #include "common/libs/utils/environment.h"
     46 #include "common/libs/utils/files.h"
     47 #include "common/libs/utils/subprocess.h"
     48 #include "common/libs/utils/size_utils.h"
     49 #include "common/vsoc/lib/vsoc_memory.h"
     50 #include "common/vsoc/shm/screen_layout.h"
     51 #include "host/commands/launch/boot_image_unpacker.h"
     52 #include "host/commands/launch/data_image.h"
     53 #include "host/commands/launch/flags.h"
     54 #include "host/commands/launch/launch.h"
     55 #include "host/commands/launch/launcher_defs.h"
     56 #include "host/commands/launch/process_monitor.h"
     57 #include "host/commands/launch/vsoc_shared_memory.h"
     58 #include "host/libs/config/cuttlefish_config.h"
     59 #include "host/commands/kernel_log_monitor/kernel_log_server.h"
     60 #include "host/libs/vm_manager/vm_manager.h"
     61 #include "host/libs/vm_manager/qemu_manager.h"
     62 
     63 using vsoc::GetPerInstanceDefault;
     64 using cvd::LauncherExitCodes;
     65 
     66 namespace {
     67 
     68 cvd::OnSocketReadyCb GetOnSubprocessExitCallback(
     69     const vsoc::CuttlefishConfig& config) {
     70   if (config.restart_subprocesses()) {
     71     return cvd::ProcessMonitor::RestartOnExitCb;
     72   } else {
     73     return cvd::ProcessMonitor::DoNotMonitorCb;
     74   }
     75 }
     76 
     77 // Maintains the state of the boot process, once a final state is reached
     78 // (success or failure) it sends the appropriate exit code to the foreground
     79 // launcher process
     80 class CvdBootStateMachine {
     81  public:
     82   CvdBootStateMachine(cvd::SharedFD fg_launcher_pipe)
     83       : fg_launcher_pipe_(fg_launcher_pipe), state_(kBootStarted) {}
     84 
     85   // Returns true if the machine is left in a final state
     86   bool OnBootEvtReceived(cvd::SharedFD boot_events_pipe) {
     87     monitor::BootEvent evt;
     88     auto bytes_read = boot_events_pipe->Read(&evt, sizeof(evt));
     89     if (bytes_read != sizeof(evt)) {
     90       LOG(ERROR) << "Fail to read a complete event, read " << bytes_read
     91                  << " bytes only instead of the expected " << sizeof(evt);
     92       state_ |= kGuestBootFailed;
     93     } else if (evt == monitor::BootEvent::BootCompleted) {
     94       LOG(INFO) << "Virtual device booted successfully";
     95       state_ |= kGuestBootCompleted;
     96     } else if (evt == monitor::BootEvent::BootFailed) {
     97       LOG(ERROR) << "Virtual device failed to boot";
     98       state_ |= kGuestBootFailed;
     99     }  // Ignore the other signals
    100 
    101     return MaybeWriteToForegroundLauncher();
    102   }
    103 
    104   bool  OnE2eTestCompleted(int exit_code) {
    105     if (exit_code != 0) {
    106       LOG(ERROR) << "VSoC e2e test failed";
    107       state_ |= kE2eTestFailed;
    108     } else {
    109       LOG(INFO) << "VSoC e2e test passed";
    110       state_ |= kE2eTestPassed;
    111     }
    112     return MaybeWriteToForegroundLauncher();
    113   }
    114 
    115   bool BootCompleted() const {
    116     bool boot_completed = state_ & kGuestBootCompleted;
    117     bool test_passed_or_disabled =
    118         (state_ & kE2eTestPassed) || (state_ & kE2eTestDisabled);
    119     bool something_failed =
    120         state_ & ~(kGuestBootCompleted | kE2eTestPassed | kE2eTestDisabled);
    121     return boot_completed && test_passed_or_disabled && !something_failed;
    122   }
    123 
    124   bool DisableE2eTests() {
    125     state_ |= kE2eTestDisabled;
    126     return MaybeWriteToForegroundLauncher();
    127   }
    128 
    129   bool BootFailed() const {
    130     return state_ & (kGuestBootFailed | kE2eTestFailed);
    131   }
    132 
    133  private:
    134   void SendExitCode(cvd::LauncherExitCodes exit_code) {
    135     fg_launcher_pipe_->Write(&exit_code, sizeof(exit_code));
    136     // The foreground process will exit after receiving the exit code, if we try
    137     // to write again we'll get a SIGPIPE
    138     fg_launcher_pipe_->Close();
    139   }
    140   bool MaybeWriteToForegroundLauncher() {
    141     if (fg_launcher_pipe_->IsOpen()) {
    142       if (BootCompleted()) {
    143         SendExitCode(cvd::LauncherExitCodes::kSuccess);
    144       } else if (state_ & kGuestBootFailed) {
    145         SendExitCode(cvd::LauncherExitCodes::kVirtualDeviceBootFailed);
    146       } else if (state_ & kE2eTestFailed) {
    147         SendExitCode(cvd::LauncherExitCodes::kE2eTestFailed);
    148       } else {
    149         // No final state was reached
    150         return false;
    151       }
    152     }
    153     // Either we sent the code before or just sent it, in any case the state is
    154     // final
    155     return true;
    156   }
    157 
    158   cvd::SharedFD fg_launcher_pipe_;
    159   int state_;
    160   static const int kBootStarted = 0;
    161   static const int kGuestBootCompleted = 1 << 0;
    162   static const int kGuestBootFailed = 1 << 1;
    163   static const int kE2eTestPassed = 1 << 2;
    164   static const int kE2eTestFailed = 1 << 3;
    165   static const int kE2eTestDisabled = 1 << 4;
    166 };
    167 
    168 // Abuse the process monitor to make it call us back when boot events are ready
    169 void SetUpHandlingOfBootEvents(
    170     cvd::ProcessMonitor* process_monitor, cvd::SharedFD boot_events_pipe,
    171     std::shared_ptr<CvdBootStateMachine> state_machine) {
    172   process_monitor->MonitorExistingSubprocess(
    173       // A dummy command, so logs are desciptive
    174       cvd::Command("boot_events_listener"),
    175       // A dummy subprocess, with the boot events pipe as control socket
    176       cvd::Subprocess(-1, boot_events_pipe),
    177       [boot_events_pipe, state_machine](cvd::MonitorEntry*) {
    178         auto sent_code = state_machine->OnBootEvtReceived(boot_events_pipe);
    179         return !sent_code;
    180       });
    181 }
    182 
    183 void LaunchE2eTestIfEnabled(cvd::ProcessMonitor* process_monitor,
    184                             std::shared_ptr<CvdBootStateMachine> state_machine,
    185                             const vsoc::CuttlefishConfig& config) {
    186   if (config.run_e2e_test()) {
    187     process_monitor->StartSubprocess(
    188         cvd::Command(config.e2e_test_binary()),
    189         [state_machine](cvd::MonitorEntry* entry) {
    190           auto test_result = entry->proc->Wait();
    191           state_machine->OnE2eTestCompleted(test_result);
    192           return false;
    193         });
    194   } else {
    195     state_machine->DisableE2eTests();
    196   }
    197 }
    198 
    199 bool WriteCuttlefishEnvironment(const vsoc::CuttlefishConfig& config) {
    200   auto env = cvd::SharedFD::Open(config.cuttlefish_env_path().c_str(),
    201                                  O_CREAT | O_RDWR, 0755);
    202   if (!env->IsOpen()) {
    203     LOG(ERROR) << "Unable to create cuttlefish.env file";
    204     return false;
    205   }
    206   std::string config_env = "export CUTTLEFISH_PER_INSTANCE_PATH=\"" +
    207                            config.PerInstancePath(".") + "\"\n";
    208   config_env += "export ANDROID_SERIAL=";
    209   if (AdbUsbEnabled(config)) {
    210     config_env += config.serial_number();
    211   } else {
    212     config_env += "127.0.0.1:" + std::to_string(GetHostPort());
    213   }
    214   config_env += "\n";
    215   env->Write(config_env.c_str(), config_env.size());
    216   return true;
    217 }
    218 
    219 // Forks and returns the write end of a pipe to the child process. The parent
    220 // process waits for boot events to come through the pipe and exits accordingly.
    221 cvd::SharedFD DaemonizeLauncher(const vsoc::CuttlefishConfig& config) {
    222   cvd::SharedFD read_end, write_end;
    223   if (!cvd::SharedFD::Pipe(&read_end, &write_end)) {
    224     LOG(ERROR) << "Unable to create pipe";
    225     return cvd::SharedFD(); // a closed FD
    226   }
    227   auto pid = fork();
    228   if (pid) {
    229     // Explicitly close here, otherwise we may end up reading forever if the
    230     // child process dies.
    231     write_end->Close();
    232     LauncherExitCodes exit_code;
    233     auto bytes_read = read_end->Read(&exit_code, sizeof(exit_code));
    234     if (bytes_read != sizeof(exit_code)) {
    235       LOG(ERROR) << "Failed to read a complete exit code, read " << bytes_read
    236                  << " bytes only instead of the expected " << sizeof(exit_code);
    237       exit_code = LauncherExitCodes::kPipeIOError;
    238     } else if (exit_code == LauncherExitCodes::kSuccess) {
    239       LOG(INFO) << "Virtual device booted successfully";
    240     } else if (exit_code == LauncherExitCodes::kVirtualDeviceBootFailed) {
    241       LOG(ERROR) << "Virtual device failed to boot";
    242     } else if (exit_code == LauncherExitCodes::kE2eTestFailed) {
    243       LOG(ERROR) << "Host VSoC region end to end test failed";
    244     } else {
    245       LOG(ERROR) << "Unexpected exit code: " << exit_code;
    246     }
    247     std::exit(exit_code);
    248   } else {
    249     // The child returns the write end of the pipe
    250     if (daemon(/*nochdir*/ 1, /*noclose*/ 1) != 0) {
    251       LOG(ERROR) << "Failed to daemonize child process: " << strerror(errno);
    252       std::exit(LauncherExitCodes::kDaemonizationError);
    253     }
    254     // Redirect standard I/O
    255     auto log_path = config.launcher_log_path();
    256     auto log =
    257         cvd::SharedFD::Open(log_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC,
    258                             S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
    259     if (!log->IsOpen()) {
    260       LOG(ERROR) << "Failed to create launcher log file: " << log->StrError();
    261       std::exit(LauncherExitCodes::kDaemonizationError);
    262     }
    263     auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY);
    264     if (!dev_null->IsOpen()) {
    265       LOG(ERROR) << "Failed to open /dev/null: " << dev_null->StrError();
    266       std::exit(LauncherExitCodes::kDaemonizationError);
    267     }
    268     if (dev_null->UNMANAGED_Dup2(0) < 0) {
    269       LOG(ERROR) << "Failed dup2 stdin: " << dev_null->StrError();
    270       std::exit(LauncherExitCodes::kDaemonizationError);
    271     }
    272     if (log->UNMANAGED_Dup2(1) < 0) {
    273       LOG(ERROR) << "Failed dup2 stdout: " << log->StrError();
    274       std::exit(LauncherExitCodes::kDaemonizationError);
    275     }
    276     if (log->UNMANAGED_Dup2(2) < 0) {
    277       LOG(ERROR) << "Failed dup2 seterr: " << log->StrError();
    278       std::exit(LauncherExitCodes::kDaemonizationError);
    279     }
    280 
    281     read_end->Close();
    282     return write_end;
    283   }
    284 }
    285 
    286 // Stops the device. If this function is successful it returns on a child of the
    287 // launcher (after it killed the laucher) and it should exit immediately
    288 bool StopCvd(vm_manager::VmManager* vm_manager) {
    289   vm_manager->Stop();
    290   auto pgid = getpgid(0);
    291   auto child_pid = fork();
    292   if (child_pid > 0) {
    293     // The parent just waits for the child to kill it.
    294     int wstatus;
    295     waitpid(child_pid, &wstatus, 0);
    296     LOG(ERROR) << "The forked child exited before delivering signal with "
    297                   "status: "
    298                << wstatus;
    299     // If waitpid returns it means the child exited before the signal was
    300     // delivered, notify the client of the error and continue serving
    301     return false;
    302   } else if (child_pid == 0) {
    303     // The child makes sure it is in a different process group before
    304     // killing everyone on its parent's
    305     // This call should never fail (see SETPGID(2))
    306     if (setpgid(0, 0) != 0) {
    307       LOG(ERROR) << "setpgid failed (" << strerror(errno)
    308                  << ") the launcher's child is about to kill itself";
    309     }
    310     killpg(pgid, SIGKILL);
    311     return true;
    312   } else {
    313     // The fork failed, the system is in pretty bad shape
    314     LOG(FATAL) << "Unable to fork before on Stop: " << strerror(errno);
    315     return false;
    316   }
    317 }
    318 
    319 void ServerLoop(cvd::SharedFD server,
    320                 vm_manager::VmManager* vm_manager) {
    321   while (true) {
    322     // TODO: use select to handle simultaneous connections.
    323     auto client = cvd::SharedFD::Accept(*server);
    324     cvd::LauncherAction action;
    325     while (client->IsOpen() && client->Read(&action, sizeof(action)) > 0) {
    326       switch (action) {
    327         case cvd::LauncherAction::kStop:
    328           if (StopCvd(vm_manager)) {
    329             auto response = cvd::LauncherResponse::kSuccess;
    330             client->Write(&response, sizeof(response));
    331             std::exit(0);
    332           } else {
    333             auto response = cvd::LauncherResponse::kError;
    334             client->Write(&response, sizeof(response));
    335           }
    336           break;
    337         default:
    338           LOG(ERROR) << "Unrecognized launcher action: "
    339                      << static_cast<char>(action);
    340           auto response = cvd::LauncherResponse::kError;
    341           client->Write(&response, sizeof(response));
    342       }
    343     }
    344   }
    345 }
    346 }  // namespace
    347 
    348 int main(int argc, char** argv) {
    349   ::android::base::InitLogging(argv, android::base::StderrLogger);
    350 
    351   auto config = InitFilesystemAndCreateConfig(&argc, &argv);
    352 
    353   auto vm_manager = vm_manager::VmManager::Get(config->vm_manager(), config);
    354 
    355   // Check host configuration
    356   std::vector<std::string> config_commands;
    357   if (!vm_manager->ValidateHostConfiguration(&config_commands)) {
    358     LOG(ERROR) << "Validation of user configuration failed";
    359     std::cout << "Execute the following to correctly configure:" << std::endl;
    360     for (auto& command : config_commands) {
    361       std::cout << "  " << command << std::endl;
    362     }
    363     std::cout << "You may need to logout for the changes to take effect"
    364               << std::endl;
    365     return LauncherExitCodes::kInvalidHostConfiguration;
    366   }
    367 
    368   if (!WriteCuttlefishEnvironment(*config)) {
    369     LOG(ERROR) << "Unable to write cuttlefish environment file";
    370   }
    371 
    372   LOG(INFO) << "The following files contain useful debugging information:";
    373   if (config->run_as_daemon()) {
    374     LOG(INFO) << "  Launcher log: " << config->launcher_log_path();
    375   }
    376   LOG(INFO) << "  Android's logcat output: " << config->logcat_path();
    377   LOG(INFO) << "  Kernel log: " << config->PerInstancePath("kernel.log");
    378   LOG(INFO) << "  Instance configuration: " << GetConfigFilePath(*config);
    379   LOG(INFO) << "  Instance environment: " << config->cuttlefish_env_path();
    380   LOG(INFO) << "To access the console run: socat file:$(tty),raw,echo=0 "
    381             << config->console_path();
    382 
    383   auto launcher_monitor_path = config->launcher_monitor_socket_path();
    384   auto launcher_monitor_socket = cvd::SharedFD::SocketLocalServer(
    385       launcher_monitor_path.c_str(), false, SOCK_STREAM, 0666);
    386   if (!launcher_monitor_socket->IsOpen()) {
    387     LOG(ERROR) << "Error when opening launcher server: "
    388                << launcher_monitor_socket->StrError();
    389     return cvd::LauncherExitCodes::kMonitorCreationFailed;
    390   }
    391   cvd::SharedFD foreground_launcher_pipe;
    392   if (config->run_as_daemon()) {
    393     foreground_launcher_pipe = DaemonizeLauncher(*config);
    394     if (!foreground_launcher_pipe->IsOpen()) {
    395       return LauncherExitCodes::kDaemonizationError;
    396     }
    397   } else {
    398     // Make sure the launcher runs in its own process group even when running in
    399     // foreground
    400     if (getsid(0) != getpid()) {
    401       int retval = setpgid(0, 0);
    402       if (retval) {
    403         LOG(ERROR) << "Failed to create new process group: " << strerror(errno);
    404         std::exit(LauncherExitCodes::kProcessGroupError);
    405       }
    406     }
    407   }
    408 
    409   auto boot_state_machine =
    410       std::make_shared<CvdBootStateMachine>(foreground_launcher_pipe);
    411 
    412   // Monitor and restart host processes supporting the CVD
    413   cvd::ProcessMonitor process_monitor;
    414 
    415   cvd::SharedFD boot_events_pipe;
    416   cvd::SharedFD adbd_events_pipe;
    417   // Only subscribe to boot events if running as daemon
    418   process_monitor.StartSubprocess(
    419       GetKernelLogMonitorCommand(*config, &boot_events_pipe, &adbd_events_pipe),
    420       GetOnSubprocessExitCallback(*config));
    421 
    422   SetUpHandlingOfBootEvents(&process_monitor, boot_events_pipe,
    423                             boot_state_machine);
    424 
    425   LaunchLogcatReceiverIfEnabled(*config, &process_monitor);
    426 
    427   LaunchUsbServerIfEnabled(*config, &process_monitor);
    428 
    429   LaunchIvServerIfEnabled(&process_monitor, *config);
    430   // Launch the e2e tests after the ivserver is ready
    431   LaunchE2eTestIfEnabled(&process_monitor, boot_state_machine, *config);
    432 
    433   // Start the guest VM
    434   process_monitor.StartSubprocess(vm_manager->StartCommand(),
    435                                   GetOnSubprocessExitCallback(*config));
    436 
    437   // Start other host processes
    438   LaunchSocketForwardProxyIfEnabled(&process_monitor, *config);
    439   LaunchSocketVsockProxyIfEnabled(&process_monitor, *config);
    440   LaunchVNCServerIfEnabled(*config, &process_monitor,
    441                            GetOnSubprocessExitCallback(*config));
    442   LaunchStreamAudioIfEnabled(*config, &process_monitor,
    443                              GetOnSubprocessExitCallback(*config));
    444   LaunchAdbConnectorIfEnabled(&process_monitor, *config, adbd_events_pipe);
    445 
    446   ServerLoop(launcher_monitor_socket, vm_manager); // Should not return
    447   LOG(ERROR) << "The server loop returned, it should never happen!!";
    448   return cvd::LauncherExitCodes::kServerError;
    449 }
    450