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
This commit is contained in:
parent
b1d92c6508
commit
b6b2afb6b3
1 changed files with 23 additions and 18 deletions
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "first_stage_console.h"
|
||||
|
||||
#include <spawn.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
|
@ -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<char**>(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<char* const*>(argv);
|
||||
char* const* envpp = const_cast<char* const*>(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<char**>(args));
|
||||
LOG(ERROR) << "unable to execv, returned " << rv << " errno " << errno;
|
||||
if (SpawnImage("/system/bin/sh")) wait(NULL);
|
||||
}
|
||||
_exit(127);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue