From b6b2afb6b3679275fc2876f0832996be35b75139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Mon, 12 Feb 2024 17:13:54 +0000 Subject: [PATCH] first_stage_console: Refactor RunScript() Introduce SpawnImage() as a reusable single-argument wrapper around posix_spawn(), to avoid having to manually manage the child process. Note that Bionic currently doesn't return the errno from the child's exec() call to the caller in the parent process, which may temporarily hide errors such as ENOENT in first_stage_console until Bionic improves. Also, this introduces a subtle change in behavior as the first_stage.sh script is now passed directly to the loader, which will only properly invoke the Shell if the file contains the right shebang. Inline the call to RunScript() to hopefully make it simpler for readers to track the lifetime of the various processes on different code paths. Test: run first_stage_init Change-Id: Ifaab2be032b2080a039209295d0b5a3759764ea7 --- init/first_stage_console.cpp | 41 ++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/init/first_stage_console.cpp b/init/first_stage_console.cpp index cb8caabd2..f6f93299b 100644 --- a/init/first_stage_console.cpp +++ b/init/first_stage_console.cpp @@ -16,6 +16,7 @@ #include "first_stage_console.h" +#include #include #include #include @@ -65,19 +66,20 @@ static bool SetupConsole() { return true; } -static void RunScript() { - LOG(INFO) << "Attempting to run /first_stage.sh..."; - pid_t pid = fork(); - if (pid != 0) { - wait(NULL); - LOG(INFO) << "/first_stage.sh exited"; - return; - } - const char* path = "/system/bin/sh"; - const char* args[] = {path, "/first_stage.sh", nullptr}; - int rv = execv(path, const_cast(args)); - LOG(ERROR) << "unable to execv /first_stage.sh, returned " << rv << " errno " << errno; - _exit(127); +static pid_t SpawnImage(const char* file) { + const char* argv[] = {file, NULL}; + const char* envp[] = {NULL}; + + char* const* argvp = const_cast(argv); + char* const* envpp = const_cast(envp); + + pid_t pid; + errno = posix_spawn(&pid, argv[0], NULL, NULL, argvp, envpp); + if (!errno) return pid; + + PLOG(ERROR) << "Failed to spawn '" << file << "'"; + + return (pid_t)0; } namespace android { @@ -99,12 +101,15 @@ void StartConsole(const std::string& cmdline) { } if (console) console = SetupConsole(); - RunScript(); + + LOG(INFO) << "Attempting to run /first_stage.sh..."; + if (SpawnImage("/first_stage.sh")) { + wait(NULL); + LOG(INFO) << "/first_stage.sh exited"; + } + if (console) { - const char* path = "/system/bin/sh"; - const char* args[] = {path, nullptr}; - int rv = execv(path, const_cast(args)); - LOG(ERROR) << "unable to execv, returned " << rv << " errno " << errno; + if (SpawnImage("/system/bin/sh")) wait(NULL); } _exit(127); }