From 5d515df178d8ea0ce7c301ad5b7ccbf676e951bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= Date: Fri, 12 Mar 2021 13:51:44 +0100 Subject: [PATCH] [Orc] Fix race condition in DebugObjectManagerPlugin During finalization the debug object is registered with the target. Materialization must wait for this process to finish. Otherwise we might start running code before the debugger finished processing the corresponding debug info. Reviewed By: lhames Differential Revision: https://reviews.llvm.org/D98417 --- .../Orc/DebugObjectManagerPlugin.cpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp b/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp index 6909928f3cf..1da87dd3468 100644 --- a/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp +++ b/lib/ExecutionEngine/Orc/DebugObjectManagerPlugin.cpp @@ -18,6 +18,7 @@ #include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/Errc.h" +#include "llvm/Support/MSVCErrorWorkarounds.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Process.h" #include "llvm/Support/raw_ostream.h" @@ -463,26 +464,38 @@ Error DebugObjectManagerPlugin::notifyEmitted( DebugObject *UnownedDebugObj = It->second.release(); PendingObjs.erase(It); + // During finalization the debug object is registered with the target. + // Materialization must wait for this process to finish. Otherwise we might + // start running code before the debugger processed the corresponding debug + // info. + std::promise FinalizePromise; + std::future FinalizeErr = FinalizePromise.get_future(); + // FIXME: We released ownership of the DebugObject, so we can easily capture // the raw pointer in the continuation function, which re-owns it immediately. if (UnownedDebugObj) UnownedDebugObj->finalizeAsync( - [this, Key, UnownedDebugObj](Expected TargetMem) { + [this, Key, UnownedDebugObj, + &FinalizePromise](Expected TargetMem) { std::unique_ptr ReownedDebugObj(UnownedDebugObj); if (!TargetMem) { - ES.reportError(TargetMem.takeError()); + FinalizePromise.set_value(TargetMem.takeError()); return; } if (Error Err = Target->registerDebugObject(*TargetMem)) { - ES.reportError(std::move(Err)); + FinalizePromise.set_value(std::move(Err)); return; } + // Registration successful, notifyEmitted() can return now and + // materialization can finish. + FinalizePromise.set_value(Error::success()); + std::lock_guard Lock(RegisteredObjsLock); RegisteredObjs[Key].push_back(std::move(ReownedDebugObj)); }); - return Error::success(); + return FinalizeErr.get(); } Error DebugObjectManagerPlugin::notifyFailed(