Don't start authfs until fd_server is ready

We pass a pipe fd to fd_server which it closes when it is ready to
accept connections. pvm_exec waits for this before triggering
compilation, which will cause authfs in the VM to connect back to
fd_server.

Also improved a bunch of error handling/error logging code, since I
managed to hit a lot of failure cases.

Fix: 201764092
Bug: 186126194
Test: atest ComposTestCase
Change-Id: I99ea5ba4fb390d47485aef3cbaaccedd046ae9fe
diff --git a/authfs/service/src/authfs.rs b/authfs/service/src/authfs.rs
index 5601738..6d87243 100644
--- a/authfs/service/src/authfs.rs
+++ b/authfs/service/src/authfs.rs
@@ -82,8 +82,11 @@
             &config.outputFdAnnotations,
             debuggable,
         )?;
-        wait_until_authfs_ready(&mountpoint).map_err(|e| {
-            debug!("Wait for authfs: {:?}", child.wait());
+        wait_until_authfs_ready(&child, &mountpoint).map_err(|e| {
+            match child.wait() {
+                Ok(status) => debug!("Wait for authfs: {}", status),
+                Err(e) => warn!("Failed to wait for child: {}", e),
+            }
             e
         })?;
 
@@ -144,13 +147,18 @@
     SharedChild::spawn(&mut command).context("Spawn authfs")
 }
 
-fn wait_until_authfs_ready(mountpoint: &OsStr) -> Result<()> {
+fn wait_until_authfs_ready(child: &SharedChild, mountpoint: &OsStr) -> Result<()> {
     let start_time = Instant::now();
     loop {
         if is_fuse(mountpoint)? {
             break;
         }
+        if let Some(exit_status) = child.try_wait()? {
+            // If the child has exited, we will never become ready.
+            bail!("Child has exited: {}", exit_status);
+        }
         if start_time.elapsed() > AUTHFS_SETUP_TIMEOUT_SEC {
+            let _ = child.kill();
             bail!("Time out mounting authfs");
         }
         sleep(AUTHFS_SETUP_POLL_INTERVAL_MS);
diff --git a/authfs/service/src/main.rs b/authfs/service/src/main.rs
index af8c7f9..890e108 100644
--- a/authfs/service/src/main.rs
+++ b/authfs/service/src/main.rs
@@ -59,7 +59,7 @@
         create_dir(&mountpoint).map_err(|e| {
             new_binder_exception(
                 ExceptionCode::SERVICE_SPECIFIC,
-                format!("Cannot create mount directory {:?}: {}", &mountpoint, e),
+                format!("Cannot create mount directory {:?}: {:?}", &mountpoint, e),
             )
         })?;
 
@@ -109,7 +109,7 @@
     Ok(())
 }
 
-fn main() -> Result<()> {
+fn try_main() -> Result<()> {
     let debuggable = env!("TARGET_BUILD_VARIANT") != "user";
     let log_level = if debuggable { log::Level::Trace } else { log::Level::Info };
     android_logger::init_once(
@@ -128,3 +128,10 @@
     ProcessState::join_thread_pool();
     bail!("Unexpected exit after join_thread_pool")
 }
+
+fn main() {
+    if let Err(e) = try_main() {
+        error!("failed with {:?}", e);
+        std::process::exit(1);
+    }
+}