Fix race condition between authfs_service and /data mounted
Currently there is a race condition between authfs_service starting and
/data/misc/authfs directory being created. If authfs_service is started
before the /data/misc/authfs has been created then authfs_service will
exit abnormally. One way this race condition is surface is
android.compos.test.ComposTestCase#testOdrefreshSpeedProfile being
flaky.
This change attempts to fix the race condition by starting the
authfs_service on post-fs-data trigger, which guarantees that
/data/misc/authfs has been prepared.
In more detail this change includes:
* Introducing new setup_config_syspros function inside the
microdroid_manager. This function is responsible for setting sysprops
derived from the payload config, e.g. if config has enable_authfs,
then microdroid.config.enable_authfs sysprop will be set. Once all the
necessary sysprops were set, microdroid_manager will set the
microdroid.config_done property.
* Adding wait_for_prop microdroid.config_done before triggering
post-fs-data action in the init.rc
* Adding on post-fs-data && prop:microdroid.config.enable_authfs=1
trigger to start authfs_service
* Moving setprop dev.bootcomplete to on boot action, and switching
microdroid_manager to wait for the dev.bootcomplete property before
running the payload.
The first three points should get rid of the race condition with
authfs_service startup, while the last one should guarantee that by the
time payload runs the authfs_service is already running.
Bug: 260361248
Bug: 260005615
Test: presubmit
Test: atest --iterations 20 android.compos.test.ComposTestCase#testOdrefreshSpeedProfile
Change-Id: Ib8d2dde5f340ffead9e681c18fa8dd18ba2dd859
diff --git a/microdroid/init.rc b/microdroid/init.rc
index 94ef940..7d04557 100644
--- a/microdroid/init.rc
+++ b/microdroid/init.rc
@@ -74,6 +74,12 @@
# some services can be started.
trigger late-fs
+ # Wait for microdroid_manager to finish setting up sysprops from the payload config.
+ # Some further actions in the boot sequence might depend on the sysprops from the payloag,
+ # e.g. microdroid.config.enable_authfs configures whether to run authfs_service after
+ # /data is mounted.
+ wait_for_prop microdroid_manager.config_done 1
+
trigger post-fs-data
# Load persist properties and override properties (if enabled) from /data.
@@ -132,6 +138,13 @@
mkdir /data/local 0751 root root
mkdir /data/local/tmp 0771 shell shell
+on post-fs-data && property:microdroid_manager.authfs.enabled=1
+ start authfs_service
+
+on boot
+ # Mark boot completed. This will notify microdroid_manager to run payload.
+ setprop dev.bootcomplete 1
+
service tombstone_transmit /system/bin/tombstone_transmit.microdroid -cid 2 -port 2000 -remove_tombstones_after_transmitting
user system
group system
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index a706dbe..17532d7 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -417,9 +417,10 @@
mount_extra_apks(&config)?;
// Wait until apex config is done. (e.g. linker configuration for apexes)
- // TODO(jooyung): wait until sys.boot_completed?
wait_for_apex_config_done()?;
+ setup_config_sysprops(&config)?;
+
// Start tombstone_transmit if enabled
if config.export_tombstones {
control_service("start", "tombstone_transmit")?;
@@ -427,11 +428,6 @@
control_service("stop", "tombstoned")?;
}
- // Start authfs if enabled
- if config.enable_authfs {
- control_service("start", "authfs_service")?;
- }
-
// Wait until zipfuse has mounted the APK so we can access the payload
wait_for_property_true(APK_MOUNT_DONE_PROP).context("Failed waiting for APK mount done")?;
@@ -442,7 +438,8 @@
ensure!(exitcode.success(), "Unable to prepare encrypted storage. Exitcode={}", exitcode);
}
- system_properties::write("dev.bootcomplete", "1").context("set dev.bootcomplete")?;
+ wait_for_property_true("dev.bootcomplete").context("failed waiting for dev.bootcomplete")?;
+ info!("boot completed, time to run payload");
exec_task(task, service).context("Failed to run payload")
}
@@ -682,6 +679,16 @@
Ok(())
}
+fn setup_config_sysprops(config: &VmPayloadConfig) -> Result<()> {
+ if config.enable_authfs {
+ system_properties::write("microdroid_manager.authfs.enabled", "1")
+ .context("failed to write microdroid_manager.authfs.enabled")?;
+ }
+ system_properties::write("microdroid_manager.config_done", "1")
+ .context("failed to write microdroid_manager.config_done")?;
+ Ok(())
+}
+
// Waits until linker config is generated
fn wait_for_apex_config_done() -> Result<()> {
wait_for_property_true(APEX_CONFIG_DONE_PROP).context("Failed waiting for apex config done")