Merge changes Ib9a6b75b,Ifb71fa24,If329e912

* changes:
  init_test: Close all file descriptors before calling execv()
  init_test: Fix a race condition
  init_test: Simplify the gentle_kill test
diff --git a/init/init_test.cpp b/init/init_test.cpp
index 7bb5c90..305bf95 100644
--- a/init/init_test.cpp
+++ b/init/init_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include <fstream>
 #include <functional>
 #include <string_view>
 #include <thread>
@@ -22,6 +23,7 @@
 #include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/properties.h>
+#include <android-base/stringprintf.h>
 #include <android/api-level.h>
 #include <gtest/gtest.h>
 #include <selinux/selinux.h>
@@ -44,6 +46,7 @@
 using android::base::GetIntProperty;
 using android::base::GetProperty;
 using android::base::SetProperty;
+using android::base::StringPrintf;
 using android::base::StringReplace;
 using android::base::WaitForProperty;
 using namespace std::literals;
@@ -643,34 +646,32 @@
     ASSERT_LE(curr_limit.rlim_max, max_limit);
 }
 
-static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
-    std::vector<const char*> argv;
-    argv.reserve(args.size() + 1);
-    for (const auto& arg : args) {
-        if (argv.empty()) {
-            LOG(DEBUG) << arg;
-        } else {
-            LOG(DEBUG) << "    " << arg;
+void CloseAllFds() {
+    DIR* dir;
+    struct dirent* ent;
+    int fd;
+
+    if ((dir = opendir("/proc/self/fd"))) {
+        while ((ent = readdir(dir))) {
+            if (sscanf(ent->d_name, "%d", &fd) == 1) {
+                close(fd);
+            }
         }
-        argv.emplace_back(arg.data());
+        closedir(dir);
     }
-    argv.emplace_back(nullptr);
-    return argv;
 }
 
-pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
-    auto argv = ConvertToArgv(args);
-
+pid_t ForkExecvpAsync(const char* argv[]) {
     pid_t pid = fork();
     if (pid == 0) {
-        close(STDIN_FILENO);
-        close(STDOUT_FILENO);
-        close(STDERR_FILENO);
+        // Child process.
+        CloseAllFds();
 
-        execvp(argv[0], const_cast<char**>(argv.data()));
+        execvp(argv[0], const_cast<char**>(argv));
         PLOG(ERROR) << "exec in ForkExecvpAsync init test";
         _exit(EXIT_FAILURE);
     }
+    // Parent process.
     if (pid == -1) {
         PLOG(ERROR) << "fork in ForkExecvpAsync init test";
         return -1;
@@ -678,6 +679,18 @@
     return pid;
 }
 
+pid_t TracerPid(pid_t pid) {
+    static constexpr std::string_view prefix{"TracerPid:"};
+    std::ifstream is(StringPrintf("/proc/%d/status", pid));
+    std::string line;
+    while (std::getline(is, line)) {
+        if (line.find(prefix) == 0) {
+            return atoi(line.substr(prefix.length()).c_str());
+        }
+    }
+    return -1;
+}
+
 TEST(init, GentleKill) {
     if (getuid() != 0) {
         GTEST_SKIP() << "Must be run as root.";
@@ -709,18 +722,15 @@
     logfile.DoNotRemove();
     ASSERT_TRUE(logfile.fd != -1);
 
-    std::vector<std::string> cmd;
-    cmd.push_back("system/bin/strace");
-    cmd.push_back("-o");
-    cmd.push_back(logfile.path);
-    cmd.push_back("-e");
-    cmd.push_back("signal");
-    cmd.push_back("-p");
-    cmd.push_back(std::to_string(pid));
-    pid_t strace_pid = ForkExecvpAsync(cmd);
+    std::string pid_str = std::to_string(pid);
+    const char* argv[] = {"/system/bin/strace", "-o", logfile.path, "-e", "signal", "-p",
+                          pid_str.c_str(),      nullptr};
+    pid_t strace_pid = ForkExecvpAsync(argv);
 
-    // Give strace a moment to connect
-    std::this_thread::sleep_for(1s);
+    // Give strace the chance to connect
+    while (TracerPid(pid) == 0) {
+        std::this_thread::sleep_for(10ms);
+    }
     service->Stop();
 
     int status;
@@ -728,8 +738,7 @@
 
     std::string logs;
     android::base::ReadFdToString(logfile.fd, &logs);
-    int pos = logs.find("killed by SIGTERM");
-    ASSERT_NE(pos, (int)std::string::npos);
+    ASSERT_NE(logs.find("killed by SIGTERM"), std::string::npos);
 }
 
 class TestCaseLogger : public ::testing::EmptyTestEventListener {