[llvm] [obj2yaml] Return from main on error instead of calling exit (PR #227594)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 30 00:56:48 PDT 2026


https://github.com/MaskRay created https://github.com/llvm/llvm-project/pull/227594

The `Fatal` lambda introduced by #224965 calls exit(1) while heap
objects are live. On the "failed to open" path the pointer to the
heap-allocated ToolOutputFile is dead, so LeakSanitizer reports a leak.
PR #227444 worked around this by defining `__lsan_is_turned_off`.

Properly fix the lsan failure by making the error callback record the
failure and return 1 from main.

LLM-aided

>From 823a127b86d268e7fca907db4fe3bff2ec468eb3 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 30 Sep 2026 00:53:02 -0700
Subject: [PATCH] [obj2yaml] Return from main on error instead of calling exit

The `Fatal` lambda introduced by #224965 calls exit(1) while heap
objects are live. On the "failed to open" path the pointer to the
heap-allocated ToolOutputFile is dead, so LeakSanitizer reports a leak.
PR #227444 worked around this by defining `__lsan_is_turned_off`.

Properly fix the lsan failure by making the error callback record the
failure and return 1 from main.

LLM-aided
---
 llvm/tools/obj2yaml/obj2yaml.cpp | 42 ++++++++++++++------------------
 1 file changed, 18 insertions(+), 24 deletions(-)

diff --git a/llvm/tools/obj2yaml/obj2yaml.cpp b/llvm/tools/obj2yaml/obj2yaml.cpp
index 848b18b8d6556..75b6b7cccfeb5 100644
--- a/llvm/tools/obj2yaml/obj2yaml.cpp
+++ b/llvm/tools/obj2yaml/obj2yaml.cpp
@@ -21,15 +21,6 @@
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/WithColor.h"
 
-#if LLVM_ADDRESS_SANITIZER_BUILD || LLVM_HWADDRESS_SANITIZER_BUILD
-#include <sanitizer/lsan_interface.h>
-static int SkipLeakCheck;
-LLVM_ATTRIBUTE_USED int __lsan_is_turned_off() { return SkipLeakCheck; }
-static void skipLeakCheck() { SkipLeakCheck = 1; }
-#else
-static void skipLeakCheck() {}
-#endif
-
 using namespace llvm;
 using namespace llvm::object;
 
@@ -119,18 +110,18 @@ static void reportError(StringRef Input, Error Err) {
 
 int main(int argc, char *argv[]) {
   InitLLVM X(argc, argv);
-  auto Fatal = [](const Twine &Msg) {
+  bool HasError = false;
+  auto ErrorFn = [&](const Twine &Msg) {
     WithColor::error(errs(), "obj2yaml") << Msg << '\n';
-    // exit() terminates without unwinding the stack or running destructors, and
-    // there is no guaranty that pointers to allocations will be preserved, so
-    // LSan reports in-flight heap allocations as leaks at atexit.
-    skipLeakCheck();
-    exit(1);
+    HasError = true;
   };
   BumpPtrAllocator A;
   StringSaver Saver(A);
   Obj2YamlOptTable Tbl;
-  opt::InputArgList Args = Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, Fatal);
+  opt::InputArgList Args =
+      Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, ErrorFn);
+  if (HasError)
+    return 1;
   if (Args.hasArg(OPT_help)) {
     Tbl.printHelp(outs(), "obj2yaml [options] <input file>",
                   "Dump a YAML description from an object file");
@@ -143,7 +134,7 @@ int main(int argc, char *argv[]) {
 
   std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
   if (Inputs.size() > 1)
-    Fatal("too many input files");
+    ErrorFn("too many input files");
   StringRef InputFilename =
       Inputs.empty() ? StringRef("-") : StringRef(Inputs[0]);
   StringRef OutputFilename = Args.getLastArgValue(OPT_o, "-");
@@ -154,19 +145,22 @@ int main(int argc, char *argv[]) {
     else if (S == "linkedit")
       RawSegment |= RawSegments::linkedit;
     else
-      Fatal("unknown segment '" + S + "' for --raw-segment");
+      ErrorFn("unknown segment '" + S + "' for --raw-segment");
   }
+  if (HasError)
+    return 1;
 
   std::error_code EC;
-  std::unique_ptr<ToolOutputFile> Out(
-      new ToolOutputFile(OutputFilename, EC, sys::fs::OF_Text));
-  if (EC)
-    Fatal("failed to open '" + OutputFilename + "': " + EC.message());
-  if (Error Err = dumpInput(InputFilename, RawSegment, Out->os())) {
+  ToolOutputFile Out(OutputFilename, EC, sys::fs::OF_Text);
+  if (EC) {
+    ErrorFn("failed to open '" + OutputFilename + "': " + EC.message());
+    return 1;
+  }
+  if (Error Err = dumpInput(InputFilename, RawSegment, Out.os())) {
     reportError(InputFilename, std::move(Err));
     return 1;
   }
-  Out->keep();
+  Out.keep();
 
   return 0;
 }



More information about the llvm-commits mailing list