Correctly daemonizes launcher

- Creates a new session (setsid)
- Closes controlling terminal
- Redirects standard I/O

Bug: 111517046
Test: local & gce
Change-Id: Ibf50946a66a646fea32b54454bf016825a4c01ab
diff --git a/host/commands/launch/main.cc b/host/commands/launch/main.cc
index 96ae736..ae6ca33 100644
--- a/host/commands/launch/main.cc
+++ b/host/commands/launch/main.cc
@@ -579,6 +579,7 @@
   config->set_kernel_log_socket_name(config->PerInstancePath("kernel-log"));
   config->set_console_path(config->PerInstancePath("console"));
   config->set_logcat_path(config->PerInstancePath("logcat"));
+  config->set_launcher_log_path(config->PerInstancePath("launcher.log"));
 
   config->set_mobile_bridge_name(FLAGS_mobile_interface);
   config->set_mobile_tap_name(FLAGS_mobile_tap_name);
@@ -672,8 +673,37 @@
     }
   } else {
     // The child returns the write end of the pipe
-    // TODO(111321286): Make the child the head of a new process group that will
-    // contain all other host processes.
+    if (daemon(/*nochdir*/ 1, /*noclose*/ 1) != 0) {
+      LOG(ERROR) << "Failed to daemonize child process: " << strerror(errno);
+      std::exit(LauncherExitCodes::kDaemonizationError);
+    }
+    // Redirect standard I/O
+    auto log_path = vsoc::CuttlefishConfig::Get()->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);
+    if (!log->IsOpen()) {
+      LOG(ERROR) << "Failed to create launcher log file: " << log->StrError();
+      std::exit(LauncherExitCodes::kDaemonizationError);
+    }
+    auto dev_null = cvd::SharedFD::Open("/dev/null", O_RDONLY);
+    if (!dev_null->IsOpen()) {
+      LOG(ERROR) << "Failed to open /dev/null: " << dev_null->StrError();
+      std::exit(LauncherExitCodes::kDaemonizationError);
+    }
+    if (dev_null->UNMANAGED_Dup2(0) < 0) {
+      LOG(ERROR) << "Failed dup2 stdin: " << dev_null->StrError();
+      std::exit(LauncherExitCodes::kDaemonizationError);
+    }
+    if (log->UNMANAGED_Dup2(1) < 0) {
+      LOG(ERROR) << "Failed dup2 stdout: " << log->StrError();
+      std::exit(LauncherExitCodes::kDaemonizationError);
+    }
+    if (log->UNMANAGED_Dup2(2) < 0) {
+      LOG(ERROR) << "Failed dup2 seterr: " << log->StrError();
+      std::exit(LauncherExitCodes::kDaemonizationError);
+    }
+
     read_end->Close();
     return write_end;
   }
@@ -733,6 +763,9 @@
   }
 
   LOG(INFO) << "The following files contain useful debugging information:";
+  if (FLAGS_daemon) {
+    LOG(INFO) << "  Launcher log: " << config->launcher_log_path();
+  }
   LOG(INFO) << "  Android's logcat output: " << config->logcat_path();
   LOG(INFO) << "  Kernel log: " << config->PerInstancePath("kernel.log");
   LOG(INFO) << "  Instance configuration: " << GetConfigFile();
diff --git a/host/libs/config/cuttlefish_config.cpp b/host/libs/config/cuttlefish_config.cpp
index 260f050..c5c6751 100644
--- a/host/libs/config/cuttlefish_config.cpp
+++ b/host/libs/config/cuttlefish_config.cpp
@@ -91,6 +91,7 @@
 const char* kKernelLogSocketName = "kernel_log_socket_name";
 const char* kConsolePath = "console_path";
 const char* kLogcatPath = "logcat_path";
+const char* kLauncherLogPath = "launcher_log_path";
 const char* kDtbPath = "dtb_path";
 
 const char* kMempath = "mempath";
@@ -302,6 +303,14 @@
   (*dictionary_)[kLogcatPath] = logcat_path;
 }
 
+std::string CuttlefishConfig::launcher_log_path() const {
+  return (*dictionary_)[kLauncherLogPath].asString();
+}
+void CuttlefishConfig::set_launcher_log_path(
+    const std::string& launcher_log_path) {
+  (*dictionary_)[kLauncherLogPath] = launcher_log_path;
+}
+
 std::string CuttlefishConfig::mobile_bridge_name() const {
   return (*dictionary_)[kMobileBridgeName].asString();
 }
diff --git a/host/libs/config/cuttlefish_config.h b/host/libs/config/cuttlefish_config.h
index 9250b3e..46ed9ac 100644
--- a/host/libs/config/cuttlefish_config.h
+++ b/host/libs/config/cuttlefish_config.h
@@ -129,6 +129,9 @@
   std::string logcat_path() const;
   void set_logcat_path(const std::string& logcat_path);
 
+  std::string launcher_log_path() const;
+  void set_launcher_log_path(const std::string& launcher_log_path);
+
   std::string mobile_bridge_name() const;
   void set_mobile_bridge_name(const std::string& mobile_bridge_name);