[PATCH] D83509: <rdar://problem/63335596> CrashTracer: clang at clang: llvm::BitstreamWriter::ExitBlock

Oliver Hunt via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Thu Jul 9 14:24:23 PDT 2020


ojhunt created this revision.
ojhunt added a reviewer: jfb.
Herald added subscribers: cfe-commits, dexonsmith.
Herald added a project: clang.

Add a guard for re-entering an SDiagsWriter's HandleDiagnostics
method after we've started finalizing. This is a generic catch
all for unexpected fatal errors so we don't recursive crash inside
the generic llvm error handler.

We also add logic to handle the actual error case in
llvm::~raw_fd_ostream caused by failing to clear errors before
it is destroyed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D83509

Files:
  clang/include/clang/Basic/DiagnosticFrontendKinds.td
  clang/lib/Frontend/SerializedDiagnosticPrinter.cpp


Index: clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
===================================================================
--- clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
+++ clang/lib/Frontend/SerializedDiagnosticPrinter.cpp
@@ -239,6 +239,9 @@
   /// generated from child processes.
   bool MergeChildRecords;
 
+  /// Whether we've started finishing and tearing down this instance.
+  bool IsFinishing = false;
+
   /// State that is shared among the various clones of this diagnostic
   /// consumer.
   struct SharedState {
@@ -568,6 +571,17 @@
 
 void SDiagsWriter::HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
                                     const Diagnostic &Info) {
+  assert(!IsFinishing &&
+         "Received a diagnostic after we've already started teardown.");
+  if (IsFinishing) {
+    SmallString<256> diagnostic;
+    Info.FormatDiagnostic(diagnostic);
+    getMetaDiags()->Report(
+        diag::warn_fe_serialized_diag_failure_during_finalisation)
+        << diagnostic;
+    return;
+  }
+
   // Enter the block for a non-note diagnostic immediately, rather than waiting
   // for beginDiagnostic, in case associated notes are emitted before we get
   // there.
@@ -761,6 +775,9 @@
 }
 
 void SDiagsWriter::finish() {
+  assert(!IsFinishing);
+  IsFinishing = true;
+
   // The original instance is responsible for writing the file.
   if (!OriginalInstance)
     return;
@@ -786,12 +803,20 @@
   if (EC) {
     getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure)
         << State->OutputFile << EC.message();
+    OS->clear_error();
     return;
   }
 
   // Write the generated bitstream to "Out".
   OS->write((char *)&State->Buffer.front(), State->Buffer.size());
   OS->flush();
+
+  assert(!OS->has_error());
+  if (OS->has_error()) {
+    getMetaDiags()->Report(diag::warn_fe_serialized_diag_failure)
+        << State->OutputFile << OS->error().message();
+    OS->clear_error();
+  }
 }
 
 std::error_code SDiagsMerger::visitStartOfDiagnostic() {
Index: clang/include/clang/Basic/DiagnosticFrontendKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -119,6 +119,9 @@
 def warn_fe_serialized_diag_failure : Warning<
     "unable to open file %0 for serializing diagnostics (%1)">,
     InGroup<SerializedDiagnostics>;
+def warn_fe_serialized_diag_failure_during_finalisation : Warning<
+    "Received warning after diagnostic serialisation teardown was underway: %0">,
+    InGroup<SerializedDiagnostics>;
 
 def err_verify_missing_line : Error<
     "missing or invalid line number following '@' in expected %0">;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D83509.276835.patch
Type: text/x-patch
Size: 2721 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200709/2a1b4b4e/attachment-0001.bin>


More information about the cfe-commits mailing list