Don't abort, return nullptr instead, when config file isn't present

Reduce the number of calls to CuttlefishConfig::Get(): We have been
abusing the singleton, which made it hard to keep track of what
happens before and after config is initialized in the launcher.

Bug: 111084325
Test: local & gce
Change-Id: I513eccacb221695fd046551d54bb8b98f7348ea8
diff --git a/host/commands/ivserver/main.cpp b/host/commands/ivserver/main.cpp
index dae1c66..16aa747 100644
--- a/host/commands/ivserver/main.cpp
+++ b/host/commands/ivserver/main.cpp
@@ -39,6 +39,10 @@
   google::ParseCommandLineFlags(&argc, &argv, true);
 
   auto config = vsoc::CuttlefishConfig::Get();
+  if (!config) {
+    LOG(ERROR) << "Unable to get cuttlefish config";
+    return 1;
+  }
 
   ivserver::IVServer server(
       ivserver::IVServerOptions(config->mempath(),
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index ca3888e..aeed54e 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -92,7 +92,7 @@
 DEFINE_string(boot_image, "", "Location of cuttlefish boot image.");
 DEFINE_int32(memory_mb, 2048,
              "Total amount of memory available for guest, MB.");
-std::string g_default_mempath{GetPerInstanceDefault("/var/run/shm/cvd-")};
+std::string g_default_mempath{vsoc::GetDefaultMempath()};
 DEFINE_string(mempath, g_default_mempath.c_str(),
               "Target location for the shmem file.");
 // The cvd-mobile-{tap|br}-xx interfaces are created by default, but libvirt
@@ -373,8 +373,7 @@
   return FLAGS_run_adb_connector && AdbTunnelEnabled();
 }
 
-void LaunchIvServer() {
-  auto config = vsoc::CuttlefishConfig::Get();
+void LaunchIvServer(vsoc::CuttlefishConfig* config) {
   // Resize gralloc region
   auto actual_width = cvd::AlignToPowerOf2(FLAGS_x_res * 4, 4);  // align to 16
   uint32_t screen_buffers_size =
@@ -468,17 +467,19 @@
   return true;
 }
 
-bool UnpackBootImage(const cvd::BootImageUnpacker& boot_image_unpacker) {
-  auto config = vsoc::CuttlefishConfig::Get();
+bool UnpackBootImage(const cvd::BootImageUnpacker& boot_image_unpacker,
+                     vsoc::CuttlefishConfig* config) {
   if (boot_image_unpacker.HasRamdiskImage()) {
-    if (!boot_image_unpacker.ExtractRamdiskImage(config->ramdisk_image_path())) {
+    if (!boot_image_unpacker.ExtractRamdiskImage(
+            config->ramdisk_image_path())) {
       LOG(ERROR) << "Error extracting ramdisk from boot image";
       return false;
     }
   }
   if (!FLAGS_kernel_path.size()) {
     if (boot_image_unpacker.HasKernelImage()) {
-      if (!boot_image_unpacker.ExtractKernelImage(config->kernel_image_path())) {
+      if (!boot_image_unpacker.ExtractKernelImage(
+              config->kernel_image_path())) {
         LOG(ERROR) << "Error extracting kernel from boot image";
         return false;
       }
@@ -490,10 +491,16 @@
   return true;
 }
 
-bool InitializeCuttlefishConfiguration(
+vsoc::CuttlefishConfig* InitializeCuttlefishConfiguration(
     const cvd::BootImageUnpacker& boot_image_unpacker) {
   auto& memory_layout = *vsoc::VSoCMemoryLayout::Get();
   auto config = vsoc::CuttlefishConfig::Get();
+  if (!config) {
+    LOG(ERROR) << "Failed to instantiate config object. Most likely because "
+                  "config file was specified and doesn't exits: '"
+               << FLAGS_config_file << "'";
+    return nullptr;
+  }
   // Set this first so that calls to PerInstancePath below are correct
   config->set_instance_dir(FLAGS_instance_dir);
 
@@ -592,7 +599,7 @@
   config->set_cuttlefish_env_path(cvd::StringFromEnv("HOME", ".") +
                                   "/.cuttlefish.sh");
 
-  return true;
+  return config;
 }
 
 bool ParseCommandLineFlags(int argc, char** argv) {
@@ -610,8 +617,7 @@
   return ResolveInstanceFiles();
 }
 
-bool WriteCuttlefishEnvironment() {
-  auto config = vsoc::CuttlefishConfig::Get();
+bool WriteCuttlefishEnvironment(vsoc::CuttlefishConfig* config) {
   auto env = cvd::SharedFD::Open(config->cuttlefish_env_path().c_str(),
                                  O_CREAT | O_RDWR, 0755);
   if (!env->IsOpen()) {
@@ -633,7 +639,7 @@
 
 // Forks and returns the write end of a pipe to the child process. The parent
 // process waits for boot events to come through the pipe and exits accordingly.
-cvd::SharedFD DaemonizeLauncher() {
+cvd::SharedFD DaemonizeLauncher(vsoc::CuttlefishConfig* config) {
   cvd::SharedFD read_end, write_end;
   if (!cvd::SharedFD::Pipe(&read_end, &write_end)) {
     LOG(ERROR) << "Unable to create pipe";
@@ -669,7 +675,7 @@
       std::exit(LauncherExitCodes::kDaemonizationError);
     }
     // Redirect standard I/O
-    auto log_path = vsoc::CuttlefishConfig::Get()->launcher_log_path();
+    auto log_path = config->launcher_log_path();
     auto log =
         cvd::SharedFD::Open(log_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC,
                             S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
@@ -702,8 +708,8 @@
 
 // Stops the device. If this function is successful it returns on a child of the
 // launcher (after it killed the laucher) and it should exit immediately
-bool StopCvd() {
-  auto vm_manager = vm_manager::VmManager::Get();
+bool StopCvd(vsoc::CuttlefishConfig* config) {
+  auto vm_manager = vm_manager::VmManager::Get(config);
   vm_manager->Stop();
   auto pgid = getpgid(0);
   auto child_pid = fork();
@@ -731,7 +737,8 @@
   }
 }
 
-void ServerLoop(cvd::SharedFD server) {
+void ServerLoop(cvd::SharedFD server,
+                vsoc::CuttlefishConfig* config) {
   while (true) {
     // TODO: use select to handle simultaneous connections.
     auto client = cvd::SharedFD::Accept(*server);
@@ -739,7 +746,7 @@
     while (client->IsOpen() && client->Read(&action, sizeof(char)) > 0) {
       switch (action) {
         case cvd::LauncherAction::kStop:
-          if (StopCvd()) {
+          if (StopCvd(config)) {
             auto response = cvd::LauncherResponse::kSuccess;
             client->Write(&response, sizeof(response));
             std::exit(0);
@@ -766,7 +773,12 @@
   }
 
   auto boot_img_unpacker = cvd::BootImageUnpacker::FromImage(FLAGS_boot_image);
-  auto vm_manager = vm_manager::VmManager::Get();
+  // Do this early so that the config object is ready for anything that needs it
+  auto config = InitializeCuttlefishConfiguration(*boot_img_unpacker);
+  if (!config) {
+    return LauncherExitCodes::kCuttlefishConfigurationInitError;
+  }
+  auto vm_manager = vm_manager::VmManager::Get(config);
 
   // Check host configuration
   std::vector<std::string> config_commands;
@@ -781,11 +793,6 @@
     return LauncherExitCodes::kInvalidHostConfiguration;
   }
 
-  // Do this early so that the config object is ready for anything that needs it
-  if (!InitializeCuttlefishConfiguration(*boot_img_unpacker)) {
-    return LauncherExitCodes::kCuttlefishConfigurationInitError;
-  }
-
   if (!vm_manager->EnsureInstanceDirExists()) {
     LOG(ERROR) << "Failed to create instance directory: " << FLAGS_instance_dir;
     return LauncherExitCodes::kInstanceDirCreationError;
@@ -796,16 +803,15 @@
     return LauncherExitCodes::kPrioFilesCleanupError;
   }
 
-  if (!UnpackBootImage(*boot_img_unpacker)) {
+  if (!UnpackBootImage(*boot_img_unpacker, config)) {
     LOG(ERROR) << "Failed to unpack boot image";
     return LauncherExitCodes::kBootImageUnpackError;
   }
 
-  if (!WriteCuttlefishEnvironment()) {
+  if (!WriteCuttlefishEnvironment(config)) {
     LOG(ERROR) << "Unable to write cuttlefish environment file";
   }
 
-  auto config = vsoc::CuttlefishConfig::Get();
   auto config_file = GetConfigFile();
   auto config_link = vsoc::GetGlobalConfigFileLink();
   // Save the config object before starting any host process
@@ -848,7 +854,7 @@
     new_action.sa_handler = SIG_IGN;
     sigaction(SIGPIPE, &new_action, &old_action);
 
-    auto pipe_fd = DaemonizeLauncher();
+    auto pipe_fd = DaemonizeLauncher(config);
     if (!pipe_fd->IsOpen()) {
       return LauncherExitCodes::kDaemonizationError;
     }
@@ -883,10 +889,10 @@
                          config->usb_ip_socket_name());
   vadb.Start();
 
-  LaunchIvServer();
+  LaunchIvServer(config);
 
   // Initialize the regions that require so before the VM starts.
-  PreLaunchInitializers::Initialize();
+  PreLaunchInitializers::Initialize(config);
 
   // Start the guest VM
   if (!vm_manager->Start()) {
@@ -899,7 +905,7 @@
   LaunchVNCServerIfEnabled();
   LaunchAdbConnectorIfEnabled();
 
-  ServerLoop(launcher_monitor_socket); // Should not return
+  ServerLoop(launcher_monitor_socket, config); // Should not return
   LOG(ERROR) << "The server loop returned, it should never happen!!";
   return cvd::LauncherExitCodes::kServerError;
 }
diff --git a/host/commands/launch/pre_launch_initializers.h b/host/commands/launch/pre_launch_initializers.h
index d5f44ed..91e97aa 100644
--- a/host/commands/launch/pre_launch_initializers.h
+++ b/host/commands/launch/pre_launch_initializers.h
@@ -16,19 +16,23 @@
  * limitations under the License.
  */
 
+#include <memory>
+
+#include <host/libs/config/cuttlefish_config.h>
+
 // Handles initialization of regions that require it strictly before the virtual
 // machine is started.
 // To add initializers for more regions declare here, implement in its own
 // source file and call from PreLaunchInitializers::Initialize().
-void InitializeScreenRegion();
-void InitializeRilRegion();
-void InitializeWifiRegion();
+void InitializeScreenRegion(vsoc::CuttlefishConfig* config);
+void InitializeRilRegion(vsoc::CuttlefishConfig* config);
+void InitializeWifiRegion(vsoc::CuttlefishConfig* config);
 
 class PreLaunchInitializers {
  public:
-  static void Initialize() {
-    InitializeScreenRegion();
-    InitializeRilRegion();
-    InitializeWifiRegion();
+  static void Initialize(vsoc::CuttlefishConfig* config) {
+    InitializeScreenRegion(config);
+    InitializeRilRegion(config);
+    InitializeWifiRegion(config);
   }
 };
diff --git a/host/commands/launch/ril_region_handler.cc b/host/commands/launch/ril_region_handler.cc
index 31f5107..224cecd 100644
--- a/host/commands/launch/ril_region_handler.cc
+++ b/host/commands/launch/ril_region_handler.cc
@@ -121,9 +121,8 @@
 };
 }  // namespace
 
-void InitializeRilRegion() {
+void InitializeRilRegion(vsoc::CuttlefishConfig* config) {
   NetConfig netconfig;
-  auto config = vsoc::CuttlefishConfig::Get();
   if (!netconfig.ObtainConfig(config->mobile_bridge_name())) {
     LOG(ERROR) << "Unable to obtain the network configuration";
     return;
diff --git a/host/commands/launch/screen_region_handler.cc b/host/commands/launch/screen_region_handler.cc
index 6e19ca1..a4bc600 100644
--- a/host/commands/launch/screen_region_handler.cc
+++ b/host/commands/launch/screen_region_handler.cc
@@ -20,10 +20,9 @@
 #include "host/commands/launch/pre_launch_initializers.h"
 #include "host/libs/config/cuttlefish_config.h"
 
-void InitializeScreenRegion() {
+void InitializeScreenRegion(vsoc::CuttlefishConfig* config) {
   auto region =
       vsoc::screen::ScreenRegionView::GetInstance(vsoc::GetDomain().c_str());
-  auto config = vsoc::CuttlefishConfig::Get();
   if (!region) {
     LOG(FATAL) << "Screen region was not found";
     return;
diff --git a/host/commands/launch/wifi_region_handler.cc b/host/commands/launch/wifi_region_handler.cc
index 9d87c64..6b68a23 100644
--- a/host/commands/launch/wifi_region_handler.cc
+++ b/host/commands/launch/wifi_region_handler.cc
@@ -24,9 +24,8 @@
 
 using vsoc::wifi::WifiExchangeView;
 
-void InitializeWifiRegion() {
+void InitializeWifiRegion(vsoc::CuttlefishConfig* config) {
   auto region = WifiExchangeView::GetInstance(vsoc::GetDomain().c_str());
-  auto config = vsoc::CuttlefishConfig::Get();
   if (!region) {
     LOG(FATAL) << "Wifi region not found";
     return;
diff --git a/host/commands/stop_cvd/main.cc b/host/commands/stop_cvd/main.cc
index 01ea156..1776cf0 100644
--- a/host/commands/stop_cvd/main.cc
+++ b/host/commands/stop_cvd/main.cc
@@ -81,8 +81,8 @@
   return ret;
 }
 
-int FallBackStop() {
-  auto vm_manager = vm_manager::VmManager::Get();
+int FallBackStop(vsoc::CuttlefishConfig* config) {
+  auto vm_manager = vm_manager::VmManager::Get(config);
   auto exit_code = 1; // Having to fallback is an error
   if (!vm_manager->Stop()) {
     LOG(ERROR)
@@ -102,7 +102,17 @@
   }
 
   return exit_code;
-  }
+}
+
+// Even if the config file can't be found, we still need a valid config object
+// with some defaults to be able to run the fallback stopping procedure
+vsoc::CuttlefishConfig* BuildSensibleConfig() {
+  vsoc::CuttlefishConfig* config(new vsoc::CuttlefishConfig());
+  config->set_instance_dir(vsoc::GetDefaultPerInstanceDir());
+  // This one is pretty safe to assume is there
+  config->set_mempath(vsoc::GetDefaultMempath());
+  return config;
+}
 }  // anonymous namespace
 
 int main(int argc, char** argv) {
@@ -110,25 +120,29 @@
   google::ParseCommandLineFlags(&argc, &argv, true);
 
   auto config = vsoc::CuttlefishConfig::Get();
+  if (!config) {
+    LOG(ERROR) << "Failed to obtain config object";
+    return FallBackStop(BuildSensibleConfig());
+  }
 
   auto monitor_path = config->launcher_monitor_socket_path();
   if (monitor_path.empty()) {
     LOG(ERROR) << "No path to launcher monitor found";
-    return FallBackStop();
+    return FallBackStop(config);
   }
   auto monitor_socket = cvd::SharedFD::SocketLocalClient(monitor_path.c_str(),
                                                          false, SOCK_STREAM);
   if (!monitor_socket->IsOpen()) {
     LOG(ERROR) << "Unable to connect to launcher monitor at " << monitor_path
                << ": " << monitor_socket->StrError();
-    return FallBackStop();
+    return FallBackStop(config);
   }
   auto request = cvd::LauncherAction::kStop;
   auto bytes_sent = monitor_socket->Send(&request, sizeof(request), 0);
   if (bytes_sent < 0) {
     LOG(ERROR) << "Error sending launcher monitor the stop command: "
                << monitor_socket->StrError();
-    return FallBackStop();
+    return FallBackStop(config);
   }
   // Perform a select with a timeout to guard against launcher hanging
   cvd::SharedFDSet read_set;
@@ -139,23 +153,23 @@
   if (selected < 0){
     LOG(ERROR) << "Failed communication with the launcher monitor: "
                << strerror(errno);
-    return FallBackStop();
+    return FallBackStop(config);
   }
   if (selected == 0) {
     LOG(ERROR) << "Timeout expired waiting for launcher monitor to respond";
-    return FallBackStop();
+    return FallBackStop(config);
   }
   cvd::LauncherResponse response;
   auto bytes_recv = monitor_socket->Recv(&response, sizeof(response), 0);
   if (bytes_recv < 0) {
     LOG(ERROR) << "Error receiving response from launcher monitor: "
                << monitor_socket->StrError();
-    return FallBackStop();
+    return FallBackStop(config);
   }
   if (response != cvd::LauncherResponse::kSuccess) {
     LOG(ERROR) << "Received '" << static_cast<char>(response)
                << "' response from launcher monitor";
-    return FallBackStop();
+    return FallBackStop(config);
   }
   LOG(INFO) << "Successfully stopped device";
   return 0;
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 2f2fffa..ba41aed 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -417,28 +417,44 @@
   (*dictionary_)[kAdbMode] = mode;
 }
 
-/*static*/ CuttlefishConfig* CuttlefishConfig::Get() {
-  static CuttlefishConfig config;
-  return &config;
-}
-
-CuttlefishConfig::CuttlefishConfig() : dictionary_(new Json::Value()) {
-  if (!FLAGS_config_file.empty()) {
-    LoadFromFile(FLAGS_config_file.c_str());
+// Creates the (initially empty) config object and populates it with values from
+// the config file if the --config_file command line argument is present.
+// Returns nullptr if there was an error loading from file
+/*static*/ CuttlefishConfig* CuttlefishConfig::BuildConfigImpl() {
+  auto ret = new CuttlefishConfig();
+  if (ret && !FLAGS_config_file.empty()) {
+    auto loaded = ret->LoadFromFile(FLAGS_config_file.c_str());
+    if (!loaded) {
+      return nullptr;
+    }
   }
+  return ret;
 }
 
-void CuttlefishConfig::LoadFromFile(const char* file) {
+/*static*/ CuttlefishConfig* CuttlefishConfig::Get() {
+  static std::shared_ptr<CuttlefishConfig> config(BuildConfigImpl());
+  return config.get();
+}
+
+CuttlefishConfig::CuttlefishConfig() : dictionary_(new Json::Value()) {}
+// Can't use '= default' on the header because the compiler complains of
+// Json::Value being an incomplete type
+CuttlefishConfig::~CuttlefishConfig() {}
+
+bool CuttlefishConfig::LoadFromFile(const char* file) {
   auto real_file_path = cvd::AbsolutePath(file);
   if (real_file_path.empty()) {
-    LOG(FATAL) << "Could not get real path for file " << file;
+    LOG(ERROR) << "Could not get real path for file " << file;
+    return false;
   }
   Json::Reader reader;
   std::ifstream ifs(real_file_path);
   if (!reader.parse(ifs, *dictionary_)) {
-    LOG(FATAL) << "Could not read config file " << file << ": "
+    LOG(ERROR) << "Could not read config file " << file << ": "
                << reader.getFormattedErrorMessages();
+    return false;
   }
+  return true;
 }
 bool CuttlefishConfig::SaveToFile(const std::string& file) const {
   std::ofstream ofs(file);
@@ -489,6 +505,10 @@
   return stream.str();
 }
 
+std::string GetDefaultMempath() {
+  return GetPerInstanceDefault("/var/run/shm/cvd-");
+}
+
 std::string DefaultHostArtifactsPath(const std::string& file_name) {
   return (cvd::StringFromEnv("ANDROID_HOST_OUT",
                              cvd::StringFromEnv("HOME", ".")) +
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 456e2ae..1516ca0 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -30,7 +30,9 @@
 class CuttlefishConfig {
  public:
   static CuttlefishConfig* Get();
-  ~CuttlefishConfig() = default;
+
+  CuttlefishConfig();
+  ~CuttlefishConfig();
 
   // Saves the configuration object in a file, it can then be read in other
   // processes by passing the --config_file option.
@@ -177,10 +179,10 @@
  private:
   std::unique_ptr<Json::Value> dictionary_;
 
-  void LoadFromFile(const char* file);
   void SetPath(const std::string& key, const std::string& path);
+  bool LoadFromFile(const char* file);
+  static CuttlefishConfig* BuildConfigImpl();
 
-  CuttlefishConfig();
   CuttlefishConfig(const CuttlefishConfig&) = delete;
   CuttlefishConfig& operator=(const CuttlefishConfig&) = delete;
 };
@@ -202,6 +204,7 @@
 int GetPerInstanceDefault(int base);
 
 std::string GetDefaultPerInstanceDir();
+std::string GetDefaultMempath();
 
 std::string DefaultHostArtifactsPath(const std::string& file);
 std::string DefaultGuestImagePath(const std::string& file);
diff --git a/host/libs/vm_manager/libvirt_manager.cpp b/host/libs/vm_manager/libvirt_manager.cpp
index 57e0cac..95f9ef0 100644
--- a/host/libs/vm_manager/libvirt_manager.cpp
+++ b/host/libs/vm_manager/libvirt_manager.cpp
@@ -269,8 +269,7 @@
   return cmd;
 }
 
-std::string BuildXmlConfig() {
-  auto config = vsoc::CuttlefishConfig::Get();
+std::string BuildXmlConfig(vsoc::CuttlefishConfig* config) {
   std::string instance_name = config->instance_name();
 
   std::unique_ptr<xmlDoc, void (*)(xmlDocPtr)> xml{xmlNewDoc(xc("1.0")),
@@ -342,12 +341,14 @@
   return out;
 }
 }  // namespace
+LibvirtManager::LibvirtManager(vsoc::CuttlefishConfig* config)
+    : VmManager(config) {}
 
 bool LibvirtManager::Start() const {
   std::string start_command = GetLibvirtCommand();
   start_command += " create /dev/fd/0";
 
-  std::string xml = BuildXmlConfig();
+  std::string xml = BuildXmlConfig(config_);
   if (FLAGS_log_xml) {
     LOG(INFO) << "Using XML:\n" << xml;
   }
@@ -371,14 +372,13 @@
 }
 
 bool LibvirtManager::Stop() const {
-  auto config = vsoc::CuttlefishConfig::Get();
   auto stop_command = GetLibvirtCommand();
-  stop_command += " destroy " + config->instance_name();
+  stop_command += " destroy " + config_->instance_name();
   return std::system(stop_command.c_str()) == 0;
 }
 
 bool LibvirtManager::EnsureInstanceDirExists() const {
-  auto instance_dir = vsoc::CuttlefishConfig::Get()->instance_dir();
+  auto instance_dir = config_->instance_dir();
   if (!cvd::DirectoryExists(instance_dir)) {
     LOG(INFO) << "Setting up " << instance_dir;
     cvd::execute({"/usr/bin/sudo", "/bin/mkdir", "-m", "0775", instance_dir});
@@ -392,10 +392,9 @@
 }
 
 bool LibvirtManager::CleanPriorFiles() const {
-  auto config = vsoc::CuttlefishConfig::Get();
-  std::string run_files = config->PerInstancePath("*") + " " +
-                          config->mempath() + " " +
-                          config->cuttlefish_env_path() + " " +
+  std::string run_files = config_->PerInstancePath("*") + " " +
+                          config_->mempath() + " " +
+                          config_->cuttlefish_env_path() + " " +
                           vsoc::GetGlobalConfigFileLink();
   LOG(INFO) << "Assuming run files of " << run_files;
   std::string fuser_cmd = "fuser " + run_files + " 2> /dev/null";
diff --git a/host/libs/vm_manager/libvirt_manager.h b/host/libs/vm_manager/libvirt_manager.h
index 2ec81af..00dfab4 100644
--- a/host/libs/vm_manager/libvirt_manager.h
+++ b/host/libs/vm_manager/libvirt_manager.h
@@ -21,7 +21,7 @@
 
 class LibvirtManager : public VmManager {
  public:
-  LibvirtManager() = default;
+  LibvirtManager(vsoc::CuttlefishConfig* config);
   virtual ~LibvirtManager() = default;
 
   bool Start() const override;
diff --git a/host/libs/vm_manager/qemu_manager.cpp b/host/libs/vm_manager/qemu_manager.cpp
index bd7765a..91d9122 100644
--- a/host/libs/vm_manager/qemu_manager.cpp
+++ b/host/libs/vm_manager/qemu_manager.cpp
@@ -46,8 +46,8 @@
 
 namespace {
 
-std::string GetMonitorPath() {
-  return vsoc::CuttlefishConfig::Get()->PerInstancePath("qemu_monitor.sock");
+std::string GetMonitorPath(vsoc::CuttlefishConfig* config) {
+  return config->PerInstancePath("qemu_monitor.sock");
 }
 
 void LogAndSetEnv(const char* key, const std::string& value) {
@@ -55,8 +55,7 @@
   LOG(INFO) << key << "=" << value;
 }
 
-int BuildAndRunQemuCmd() {
-  auto config = vsoc::CuttlefishConfig::Get();
+int BuildAndRunQemuCmd(vsoc::CuttlefishConfig* config) {
   // Set the config values in the environment
   LogAndSetEnv("qemu_binary", FLAGS_qemu_binary);
   LogAndSetEnv("instance_name", config->instance_name());
@@ -89,13 +88,16 @@
 }
 
 }  // namespace
+QemuManager::QemuManager(vsoc::CuttlefishConfig* config)
+  : VmManager(config) {}
 
 bool QemuManager::Start() const {
   // Create a thread that will make the launcher abort if the qemu process
   // crashes, this avoids having the launcher waiting forever for
   // VIRTUAL_DEVICE_BOOT_COMPLETED in this cases.
-  std::thread waiting_thread([]() {
-    int status = BuildAndRunQemuCmd();
+  auto config = this->config_;
+  std::thread waiting_thread([config]() {
+    int status = BuildAndRunQemuCmd(config);
     if (status != 0) {
       LOG(FATAL) << "Qemu process exited prematurely";
     } else {
@@ -117,7 +119,7 @@
   struct sockaddr_un addr;
   memset(&addr, 0, sizeof(addr));
   addr.sun_family = AF_UNIX;
-  std::string monitor_path = GetMonitorPath();
+  std::string monitor_path = GetMonitorPath(config_);
   strncpy(addr.sun_path, monitor_path.c_str(), sizeof(addr.sun_path) - 1);
 
   if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
@@ -146,7 +148,7 @@
 }
 
 bool QemuManager::EnsureInstanceDirExists() const {
-  auto instance_dir = vsoc::CuttlefishConfig::Get()->instance_dir();
+  auto instance_dir = config_->instance_dir();
   if (!cvd::DirectoryExists(instance_dir.c_str())) {
     LOG(INFO) << "Setting up " << instance_dir;
     if (mkdir(instance_dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
@@ -158,10 +160,9 @@
 
 }
 bool QemuManager::CleanPriorFiles() const {
-  auto config = vsoc::CuttlefishConfig::Get();
-  std::string run_files = config->PerInstancePath("*") + " " +
-                          config->mempath() + " " +
-                          config->cuttlefish_env_path() + " " +
+  std::string run_files = config_->PerInstancePath("*") + " " +
+                          config_->mempath() + " " +
+                          config_->cuttlefish_env_path() + " " +
                           vsoc::GetGlobalConfigFileLink();
   LOG(INFO) << "Assuming run files of " << run_files;
   std::string fuser_cmd = "fuser " + run_files + " 2> /dev/null";
diff --git a/host/libs/vm_manager/qemu_manager.h b/host/libs/vm_manager/qemu_manager.h
index 2c9ac14..0d5045a 100644
--- a/host/libs/vm_manager/qemu_manager.h
+++ b/host/libs/vm_manager/qemu_manager.h
@@ -23,7 +23,7 @@
 // package to support the qemu-cli capability.
 class QemuManager : public VmManager {
  public:
-  QemuManager() = default;
+  QemuManager(vsoc::CuttlefishConfig* config);
   virtual ~QemuManager() = default;
 
   bool Start() const override;
diff --git a/host/libs/vm_manager/vm_manager.cpp b/host/libs/vm_manager/vm_manager.cpp
index 0fc69c5..deb73c7 100644
--- a/host/libs/vm_manager/vm_manager.cpp
+++ b/host/libs/vm_manager/vm_manager.cpp
@@ -24,11 +24,16 @@
 #include "host/libs/vm_manager/qemu_manager.h"
 
 namespace vm_manager {
-std::shared_ptr<VmManager> VmManager::Get() {
+
+VmManager::VmManager(vsoc::CuttlefishConfig* config)
+    : config_(config) {}
+
+std::shared_ptr<VmManager> VmManager::Get(
+    vsoc::CuttlefishConfig* config) {
   static std::shared_ptr<VmManager> vm_manager(
       vsoc::HostSupportsQemuCli()
-          ? std::shared_ptr<VmManager>(new QemuManager())
-          : std::shared_ptr<VmManager>(new LibvirtManager()));
+          ? std::shared_ptr<VmManager>(new QemuManager(config))
+          : std::shared_ptr<VmManager>(new LibvirtManager(config)));
   return vm_manager;
 }
 
diff --git a/host/libs/vm_manager/vm_manager.h b/host/libs/vm_manager/vm_manager.h
index 4dffba7..9eb1ffc 100644
--- a/host/libs/vm_manager/vm_manager.h
+++ b/host/libs/vm_manager/vm_manager.h
@@ -19,6 +19,8 @@
 #include <string>
 #include <vector>
 
+#include <host/libs/config/cuttlefish_config.h>
+
 namespace vm_manager {
 
 // Superclass of every guest VM manager. It provides a static getter that
@@ -27,7 +29,8 @@
 class VmManager {
  public:
   // Returns the most suitable vm manager as a singleton.
-  static std::shared_ptr<VmManager> Get();
+  static std::shared_ptr<VmManager> Get(
+      vsoc::CuttlefishConfig* config);
   virtual ~VmManager() = default;
 
   virtual bool Start() const = 0;
@@ -42,6 +45,8 @@
  protected:
   static bool UserInGroup(const std::string& group,
                           std::vector<std::string>* config_commands);
+  vsoc::CuttlefishConfig* config_;
+  VmManager(vsoc::CuttlefishConfig* config);
 };
 
 }  // namespace vm_manager