Assertion failure in Cling when attempting to jit code from multiple threads
Los mantenedores suelen responder en 1 día
@devajithvs ya está trabajando en esto.
Desde el 4/12/2025.
Evaluación
Este issue todavía no se ha evaluado.
Descripción
Check duplicate issues.
- Checked for duplicates
Description
Jitting from multithreaded code in some circumstances triggers an assertion in Cling:
root/interpreter/cling/lib/Interpreter/IncrementalParser.cpp:513: IncrementalParser::ParseResultTransaction cling::IncrementalParser::endTransaction(Transaction *): Assertion `(*I)->isCompleted() && "Nested transaction not completed!?"' failed.
Inspecting the value of *I reveals an invalid pointer, indicating that memory corruption happens somewhere.
Reproducer
This is the unit test where the bug was spotted originally; it can probably be simplified quite a bit but it is a reliable reproducer when built in debug mode.
#include <gtest/gtest.h>
#include <thread>
#include <memory>
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleWriter.hxx>
#include <ROOT/RNTupleReader.hxx>
#include <ROOT/RNTupleModel.hxx>
#include <ROOT/TestSupport.hxx>
#include "TParallelMergingFile.h"
#include "TServerSocket.h"
#include "TFileMerger.h"
enum EStatusKind {
// These values are dictated by TParallelMergingFile::UploadAndReset().
kStartConnection = 0,
kProtocolVersion = 1,
kProtocol = 1,
};
static void Server(std::unique_ptr<TServerSocket> ss, const std::string &outFile)
{
// NOTE: only accepts a single client.
auto client = std::unique_ptr<TSocket>(ss->Accept());
ASSERT_NE(client, nullptr);
// initial handshake
UInt_t clientIdx = 0;
client->Send(clientIdx, kStartConnection);
client->Send(kProtocolVersion, kProtocol);
TFileMerger merger{/* isLocal = */ false};
merger.SetMergeOptions(TString("rntuple.MergingMode=Union"));
bool ok = merger.OutputFile(outFile.c_str(), "RECREATE");
ASSERT_TRUE(ok);
// Client loop
bool alive = true;
while (alive) {
TMessage *msg = nullptr;
client->Recv(msg);
ASSERT_NE(msg, nullptr);
switch (msg->What()) {
case kMESS_STRING: {
// This is how the TParallelMergingFile terminates its connection (it sends a message containing
// the string "Finished").
char str[64];
msg->ReadString(str, sizeof(str));
alive = false;
} break;
case kMESS_ANY: {
// Receive and merge data
Int_t clientId;
TString filename;
Long64_t length;
msg->ReadInt(clientId);
msg->ReadTString(filename);
msg->ReadLong64(length);
auto input = std::make_unique<TMemFile>((std::string("server_") + filename), msg->Buffer() + msg->Length(),
length, "READ");
msg->SetBufferOffset(msg->Length() + length);
EXPECT_NE(input->Get<ROOT::RNTuple>("ntpl"), nullptr);
merger.AddFile(input.get());
bool ok = merger.PartialMerge(TFileMerger::kAllIncremental | TFileMerger::kKeepCompression);
EXPECT_TRUE(ok);
} break;
default: std::cout << "ignoring message of kind " << msg->What() << "\n";
}
delete msg;
}
}
TEST(TParallelMergingFile, UploadAndResetNonTObject)
{
constexpr auto sockPath = "/tmp/parallelMergeTest.sock";
// Start server
gSystem->Unlink(sockPath);
auto ss = std::make_unique<TServerSocket>(sockPath);
ASSERT_TRUE(ss->IsValid());
struct Cleanup {
const char *fSockPath;
Cleanup(const char *sockPath) : fSockPath(sockPath) {}
~Cleanup() { gSystem->Unlink(fSockPath); }
} cleanup(sockPath);
ROOT::TestSupport::FileRaii fileGuardMerged("parallelFileMerged.root");
std::thread serverThread(Server, std::move(ss), fileGuardMerged.GetPath());
// Create "client-side" file
auto *file = dynamic_cast<TParallelMergingFile *>(
TFile::Open((std::string("parallelMergeTest.root?pmerge=") + sockPath).c_str(), "RECREATE"));
ASSERT_NE(file, nullptr);
file->SetCacheWrite(nullptr);
ROOT::TestSupport::CheckDiagsRAII diags;
diags.optionalDiag(kWarning, "TParallelMergingFile::ResetObjects", "can not be ResetAfterMerge", false);
diags.requiredDiag(kWarning, "TFileMerger::MergeRecursive", "Merging RNTuples is experimental");
constexpr auto kNEntries = 10000;
constexpr auto kNUploads = 4;
{
auto model = ROOT::RNTupleModel::CreateBare();
model->MakeField<float>("px");
model->MakeField<float>("py");
auto writer = ROOT::RNTupleWriter::Append(model->Clone(), "ntpl", *file);
auto entry = writer->CreateEntry();
auto px = entry->GetPtr<float>("px");
auto py = entry->GetPtr<float>("py");
for (int i = 0; i < kNEntries; ++i) {
*px = i;
*py = 2 * i;
writer->Fill(*entry);
if (i > 0 && (i % (kNEntries / kNUploads)) == 0) {
// Force UploadAndReset() by destroying the RNTupleWriter, which in turn will call CommitDataset()
// which ultimately calls file->Write().
// IMPORTANT: writer.reset() must be called explicitly, since we must not create the new RNTuple
// before destroying the old one (otherwise the header will get a stale address and end up corrupted).
writer.reset();
writer = ROOT::RNTupleWriter::Append(model->Clone(), "ntpl", *file);
entry = writer->CreateEntry();
px = entry->GetPtr<float>("px");
py = entry->GetPtr<float>("py");
}
}
}
delete file;
serverThread.join();
{
auto reader = ROOT::RNTupleReader::Open("ntpl", fileGuardMerged.GetPath());
EXPECT_EQ(reader->GetNEntries(), kNEntries);
auto px = reader->GetModel().GetDefaultEntry().GetPtr<float>("px");
auto py = reader->GetModel().GetDefaultEntry().GetPtr<float>("py");
for (auto idx : reader->GetEntryRange()) {
reader->LoadEntry(idx);
EXPECT_FLOAT_EQ(*px, idx);
EXPECT_FLOAT_EQ(*py, 2 * idx);
}
}
}
ROOT version
master
Installation method
source
Operating system
ArchLinux
Additional context
No response
- Lenguaje dominante
- C++
- Estrellas
- 3.3k
- Forks
- 1.6k
- Merge medio
- 2 d 17 h
- PR fusionados (30 d)
- 188
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de root-project/root
-
thisroot.sh: wrong ROOTSYS in zsh when the shell's command line has a newlinePosiblemente ocupada @dpiparo la tomó hace 4 días. Abiertobug in:Build System
Dificultad 2/5 1-3 horas Aptitud para principiantes 86/100
root-project/root#23746 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[tmva][sofie] Inputs of unsupported type (e.g. float16) give code that does not compile instead of an errorPosiblemente ocupada @lmoneta la tomó hace 14 días. AbiertoAI-Assisted bug in:SOFIE
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
root-project/root#23655 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
[RDataFrame] Code that transforms `#var` alias to `R_rdf_sizeof_var` does not respect string literalsPosiblemente ocupada @vepadulano la tomó hace 1 día. Abiertobug in:RDataFrame
Dificultad 3/5 1-2 días Aptitud para principiantes 71/100
root-project/root#23790 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
TDataMember::GetOffset interfers to TDataMember::GetOffsetCintPosiblemente ocupada @pcanal la tomó hace 1 día. Abiertobug in:Core Libraries
Dificultad 4/5 3-5 días Aptitud para principiantes 48/100
root-project/root#23777 · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
`TChain::GetEntries` internal caching ineffective?Posiblemente ocupada @pcanal la tomó hace 7 días. Abiertoimprovement in:TTree
root-project/root#23738 · 2 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de root-project/root
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
foxglove/mcap#1907 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
telegramdesktop/tdesktop#31505 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
Los mantenedores suelen responder en 1 día
-
ll-builder shell completions omit existing lockfile commands and --lockedPosiblemente ocupada @project-nju-learner la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 90/100
OpenAtom-Linyaps/linyaps#2291 ·
Los mantenedores suelen responder en 1 día