fix bug with elf object left with file open upon error causing Entered fatal signal...
authorLaurent Demailly <ldemailly@fb.com>
Wed, 17 Dec 2014 01:56:51 +0000 (17:56 -0800)
committerJoelMarcey <joelm@fb.com>
Thu, 18 Dec 2014 20:29:40 +0000 (12:29 -0800)
Summary: fix bug with elf object left with file open upon error causing Entered fatal signal handler recursively later

Test Plan: run publisher at the limit

Reviewed By: tudorb@fb.com

Subscribers: trunkagent, chip, folly-diffs@

FB internal diff: D1743052

Tasks: 5752190

Signature: t1:1743052:1418780889:ad2ee0e6999cf417c2b9fd1ef6bc82d2086774a1

folly/experimental/symbolizer/Elf.cpp
folly/experimental/symbolizer/Elf.h

index 6b32dc1215bc1b83e2ea8664dd59a374b58124d8..00b0e9ef32d4351b961f61c9d9fe649b471e7b86 100644 (file)
@@ -28,6 +28,7 @@
 
 #include <folly/Conv.h>
 #include <folly/Exception.h>
+#include <folly/ScopeGuard.h>
 
 namespace folly {
 namespace symbolizer {
@@ -65,7 +66,10 @@ int ElfFile::openNoThrow(const char* name, bool readOnly, const char** msg)
     if (msg) *msg = "open";
     return kSystemError;
   }
-
+  // Always close fd and unmap in case of failure along the way to avoid
+  // check failure above if we leave fd != -1 and the object is recycled
+  // like it is inside SignalSafeElfCache
+  ScopeGuard guard = makeGuard([&]{ reset(); });
   struct stat st;
   int r = fstat(fd_, &st);
   if (r == -1) {
@@ -87,12 +91,12 @@ int ElfFile::openNoThrow(const char* name, bool readOnly, const char** msg)
     errno = EINVAL;
     return kInvalidElfFile;
   }
-
+  guard.dismiss();
   return kSuccess;
 }
 
 ElfFile::~ElfFile() {
-  destroy();
+  reset();
 }
 
 ElfFile::ElfFile(ElfFile&& other) noexcept
@@ -108,7 +112,7 @@ ElfFile::ElfFile(ElfFile&& other) noexcept
 
 ElfFile& ElfFile::operator=(ElfFile&& other) {
   assert(this != &other);
-  destroy();
+  reset();
 
   fd_ = other.fd_;
   file_ = other.file_;
@@ -123,13 +127,15 @@ ElfFile& ElfFile::operator=(ElfFile&& other) {
   return *this;
 }
 
-void ElfFile::destroy() {
+void ElfFile::reset() {
   if (file_ != MAP_FAILED) {
     munmap(file_, length_);
+    file_ = static_cast<char*>(MAP_FAILED);
   }
 
   if (fd_ != -1) {
     close(fd_);
+    fd_ = -1;
   }
 }
 
index 9a58ba2f3e96a365da604e2861667ed7a7586528..fe96354a5d835b8ba7a9a7897a45998b843ca1fe 100644 (file)
@@ -193,7 +193,7 @@ class ElfFile {
 
  private:
   bool init(const char** msg);
-  void destroy();
+  void reset();
   ElfFile(const ElfFile&) = delete;
   ElfFile& operator=(const ElfFile&) = delete;