Add record_allocs_on_exit option.

Add a config parameter "record_allocs_on_exit" that will cause the
currently recorded set of allocs to be dumped to a file when
the process exits.

Update the documentation, and add new unit tests.

Test: Unit tests pass.
Change-Id: I81d31bc63b8a6709697533c5099dcc6444c11d47
diff --git a/libc/malloc_debug/RecordData.cpp b/libc/malloc_debug/RecordData.cpp
index 8a77170..79e051b 100644
--- a/libc/malloc_debug/RecordData.cpp
+++ b/libc/malloc_debug/RecordData.cpp
@@ -131,17 +131,30 @@
   record_obj_->WriteEntries();
 }
 
+void RecordData::WriteEntriesOnExit() {
+  if (record_obj_ == nullptr) return;
+
+  // Append the current pid to the file name to avoid multiple processes
+  // writing to the same file.
+  std::string file(record_obj_->file());
+  file += "." + std::to_string(getpid());
+  record_obj_->WriteEntries(file);
+}
+
 void RecordData::WriteEntries() {
+  WriteEntries(file_);
+}
+
+void RecordData::WriteEntries(const std::string& file) {
   std::lock_guard<std::mutex> entries_lock(entries_lock_);
   if (cur_index_ == 0) {
     info_log("No alloc entries to write.");
     return;
   }
 
-  int dump_fd =
-      open(dump_file_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 0755);
+  int dump_fd = open(file.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 0755);
   if (dump_fd == -1) {
-    error_log("Cannot create record alloc file %s: %s", dump_file_.c_str(), strerror(errno));
+    error_log("Cannot create record alloc file %s: %s", file.c_str(), strerror(errno));
     return;
   }
 
@@ -179,7 +192,7 @@
 
   entries_.resize(config.record_allocs_num_entries());
   cur_index_ = 0U;
-  dump_file_ = config.record_allocs_file();
+  file_ = config.record_allocs_file();
 
   return true;
 }