Merge "Add the two best build system janitors."
diff --git a/init/README.md b/init/README.md
index b2039b4..d86f077 100644
--- a/init/README.md
+++ b/init/README.md
@@ -277,10 +277,6 @@
   since it has some peculiarities for backwards compatibility reasons. The 'imports' section of
   this file has more details on the order.
 
-`parse_apex_configs`
-  Parses config file(s) from the mounted APEXes. Intented to be used only once
-  when apexd notifies the mount event by setting apexd.status to ready.
-
 `priority <priority>`
 > Scheduling priority of the service process. This value has to be in range
   -20 to 19. Default priority is 0. Priority is set via setpriority().
@@ -512,6 +508,10 @@
   _options_ include "barrier=1", "noauto\_da\_alloc", "discard", ... as
   a comma separated string, eg: barrier=1,noauto\_da\_alloc
 
+`parse_apex_configs`
+> Parses config file(s) from the mounted APEXes. Intented to be used only once
+  when apexd notifies the mount event by setting apexd.status to ready.
+
 `restart <service>`
 > Stops and restarts a running service, does nothing if the service is currently
   restarting, otherwise, it just starts the service.
diff --git a/libbacktrace/UnwindStack.h b/libbacktrace/UnwindStack.h
index 33c4282..4ec591d 100644
--- a/libbacktrace/UnwindStack.h
+++ b/libbacktrace/UnwindStack.h
@@ -58,7 +58,7 @@
 
   bool Unwind(size_t num_ignore_frames, void* context) override;
 
-  std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset);
+  std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) override;
 
   size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) override;
 
diff --git a/libprocessgroup/cgroup_map.cpp b/libprocessgroup/cgroup_map.cpp
index b3b497f..41a6e6e 100644
--- a/libprocessgroup/cgroup_map.cpp
+++ b/libprocessgroup/cgroup_map.cpp
@@ -229,9 +229,11 @@
 
 static bool WriteRcFile(const std::map<std::string, CgroupDescriptor>& descriptors) {
     std::string cgroup_rc_path = StringPrintf("%s/%s", CGROUPS_RC_DIR, CgroupMap::CGROUPS_RC_FILE);
-    unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(),
-                                         O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
-                                         S_IRUSR | S_IRGRP | S_IROTH)));
+    // Let init keep the FD open to prevent file mappings from becoming invalid
+    // in case the file gets deleted somehow
+    static unique_fd fd(TEMP_FAILURE_RETRY(open(cgroup_rc_path.c_str(),
+                                                O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC,
+                                                S_IRUSR | S_IRGRP | S_IROTH)));
     if (fd < 0) {
         PLOG(ERROR) << "open() failed for " << cgroup_rc_path;
         return false;
@@ -412,6 +414,19 @@
 bool CgroupMap::SetupCgroups() {
     std::map<std::string, CgroupDescriptor> descriptors;
 
+    if (getpid() != 1) {
+        LOG(ERROR) << "Cgroup setup can be done only by init process";
+        return false;
+    }
+
+    // Make sure we do this only one time. No need for std::call_once because
+    // init is a single-threaded process
+    static bool setup_done = false;
+    if (setup_done) {
+        LOG(WARNING) << "Attempt to call SetupCgroups more than once";
+        return true;
+    }
+
     // load cgroups.json file
     if (!ReadDescriptors(&descriptors)) {
         LOG(ERROR) << "Failed to load cgroup description file";
@@ -449,6 +464,7 @@
         return false;
     }
 
+    setup_done = true;
     return true;
 }