Crash when writing canvas to TFile

I am seeing a sporadic crash in one of my scripts, it only happens sometimes. I was wondering if an expert eye might now what’s going on based on the stack trace.

#6 0x00007efcd42d5d16 in TBufferFile::WriteFastArray(double const*, int) () from /opt/root/lib/libRIO.so
#7 0x00007efcd50f270f in TStreamerBase::WriteBuffer(TBuffer&, char*) () from /opt/root/lib/libCore.so.6.28
#8 0x00007efcd456a73c in int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) () from /opt/root/lib/libRIO.so
#9 0x00007efcd43b5db4 in TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) () from /opt/root/lib/libRIO.so
#10 0x00007efcd42dd0d5 in TBufferFile::WriteClassBuffer(TClass const*, void*) () from /opt/root/lib/libRIO.so
#11 0x00007efcd42dc7bb in TBufferFile::WriteObjectClass(void const*, TClass const*, bool) () from /opt/root/lib/libRIO.so
#12 0x00007efcd42e3fe4 in TBufferIO::WriteObjectAny(void const*, TClass const*, bool) () from /opt/root/lib/libRIO.so
#13 0x00007efcd5071894 in TList::Streamer(TBuffer&) () from /opt/root/lib/libCore.so.6.28
#14 0x00007efcd42d6d4a in TBufferFile::WriteFastArray(void**, TClass const*, int, bool, TMemberStreamer*) () from /opt/root/lib/libRIO.so
#15 0x00007efcd4568096 in int TStreamerInfo::WriteBufferAux<char**>(TBuffer&, char** const&, TStreamerInfo::TCompInfo* const*, int, int, int, int, int) () from /opt/root/lib/libRIO.so
#16 0x00007efcd43b5db4 in TStreamerInfoActions::GenericWriteAction(TBuffer&, void*, TStreamerInfoActions::TConfiguration const*) () from /opt/root/lib/libRIO.so
#17 0x00007efcd42dd0d5 in TBufferFile::WriteClassBuffer(TClass const*, void*) () from /opt/root/lib/libRIO.so
#18 0x00007efcb1c43f70 in TCanvas::Streamer(TBuffer&) () from /opt/root/lib/libGpad.so.6.28.02
#19 0x00007efcd438dc9d in TKey::TKey(TObject const*, char const*, int, TDirectory*) () from /opt/root/lib/libRIO.so
#20 0x00007efcd434af69 in TFile::CreateKey(TDirectory*, TObject const*, char const*, int) () from /opt/root/lib/libRIO.so
#21 0x00007efcd433ba01 in TDirectoryFile::WriteTObject(TObject const*, char const*, char const*, int) () from /opt/root/lib/libRIO.so
#22 0x00007efcd4ff31cd in TObject::Write(char const*, int, int) const () from /opt/root/lib/libCore.so.6.28
#23 0x00007efccb043849 in draw(TString) () from /tmp/home/user/draw_cpp.so

I have extracted a snippet of the involved part of the code.

#include <iostream>
#include <fstream>
#include <cmath>
//~ #include <set>
#include <numeric>

using std::cout;
using std::endl;

#include "TMath.h"
#include "TH2.h"
#include "TStyle.h"
#include "TLatex.h"
#include "TTree.h"
#include "TPaveStats.h"
#include "TFile.h"
#include "TCanvas.h"
#include "TROOT.h"

const UInt_t kWidth=1200;//Canvas size for png output resolution
const UInt_t kHeight=kWidth*0.75;

void ResizeCanvas(TCanvas* const c, const UInt_t width, const UInt_t height)
{
    if(!c) return;
    if(gROOT->IsBatch())
    {
        c->SetCanvasSize(width,height);
    }
    else
    {
        c->SetWindowSize(width,height);
    }
}

TCanvas* CreateCanvas(const TString name)
{
    TCanvas* const c = new TCanvas(name,name,100 ,100, kWidth, kHeight);
    ResizeCanvas(c,kWidth,kHeight);

    c->SetFillColor(0);
    c->SetFillStyle(0);
    c->SetFrameFillColor(0);
    c->SetFrameFillStyle(0);
    c->Draw();

    return c;
}

void reformat_stats(TH1* h)
{
    gPad->Update();
    TPaveStats *st = ((TPaveStats*)h->FindObject("stats"));
    st->SetFillStyle(0);
    st->SetX1NDC(0.69);
    st->SetX2NDC(0.89);
    st->SetY1NDC(0.85);
    st->SetY2NDC(0.99);
}

void draw(const TString outputDir="/tmp/")
{
    const ULong64_t nChunks = 200;
    const ULong64_t chunkSize = 512ULL*1024*1024; // 512 MB was the readout chunk size in the whole ELBE campaign
    const ULong64_t chunkSamples = chunkSize/2;
    const ULong64_t windowSamples = 250; // samples
    const ULong64_t preTrigger = 10; // samples
    const double time_step_ns = 0.4; // ns
    const double bin_width_time = 0.001; //s

    TH2D* h2_trig_raw = new TH2D("h2_trig_raw", "", windowSamples, -time_step_ns*preTrigger, (windowSamples-preTrigger)*time_step_ns, 16384, 0, 16384);
    h2_trig_raw->SetContour(255);
    h2_trig_raw->GetXaxis()->SetTitle("Time relative to trigger / ns");
    h2_trig_raw->GetYaxis()->SetTitle("ADC");
    const UInt_t nbins_time = TMath::Nint( nChunks * chunkSamples * time_step_ns / 1e9 / bin_width_time);
    const double length_x_time = bin_width_time * nbins_time; // s
    TH1D* h_abs_time = new TH1D("h_abs_time", "", nbins_time, 0, length_x_time);
    h_abs_time->GetXaxis()->SetTitle("Time / s");
    h_abs_time->GetYaxis()->SetTitle("Count rate / cps");

    TLatex* text = new TLatex(0.2, 0.04, "/a/b/cdee/fff/");
    text->SetNDC();  // Set NDC coordinate system
    text->SetTextAlign(21);  // Left alignment (10) + bottom (3) = 13 (https://root.cern/doc/v608/TAttText_8h_source.html line 58)
    text->SetTextSize(0.02);
    TFile* out = new TFile(outputDir+"/plots.root", "RECREATE");
    auto c2 = CreateCanvas("c_trig_raw");
    c2->SetSupportGL(true);
    c2->SetGridx();
    c2->SetGridy();
    c2->SetLogz();
    h2_trig_raw->Draw("COLZ");
    reformat_stats(h2_trig_raw);
    text->Draw();
    c2->SaveAs(outputDir + "/" + c2->GetName() + ".png");
    c2->Write();
    c2 = CreateCanvas("c_abs_time");
    c2->SetSupportGL(true);
    c2->SetGridx();
    c2->SetGridy();
    c2->SetLogy();
    h_abs_time->Draw();
    reformat_stats(h_abs_time);
    text->Draw();
    c2->SaveAs(outputDir + "/" + c2->GetName() + ".png");
    c2->Write();
    out->Close();
}

Maybe it’s not a good idea that the TLatex object is drawn on several canvases at the same time, and that causes the crash (but only sometimes)?

I see same issue in 6.30.02 and 6.28.02

   ------------------------------------------------------------------
  | Welcome to ROOT 6.30/02                        https://root.cern |
  | (c) 1995-2023, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Nov 27 2023, 19:50:38                 |
  | From tags/v6-30-02@                                              |
  | With c++ (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0                   |
  | Try '.help'/'.?', '.demo', '.license', '.credits', '.quit'/'.q'  |
   ------------------------------------------------------------------

Hi @ferhue,
thank you reporting this.

I tried to run your code a few times and I didn’t occur into a crash, but it might have been just by chance. I wonder if @pcanal or @couet could help with this…

Cheers,
Monica

1 Like

I tried a few time (on Mac with master0 and it dow not crash for me. I am not sure what the problem could be.

I you do not make a TLatex do you get the crash also ?

Thanks.
I will try. But I only get the crash very very rarely, so it’s hard to debug. I also just shared the minimized version, usually I have a longer script with many more histograms and filling them with tons of data, so not sure if the ‘minimized version’ shows the crash or not… sorry

I see you are writing:

Processing draw.C...
Info in <TCanvas::Print>: file /tmp//c_trig_raw.png has been created
Info in <TCanvas::Print>: file /tmp//c_abs_time.png has been created

You are writing in /tmp, which should not be an issue. But could it be that sometimes your /tmp is somehow “not writable” (as I said it should not) ?

Also not you have an extra / in the path, but that’s not a problem either.

The crash I saw once with a path in /home/user/desktop, so that can’t be.

The only thing I noticed once is that the crash happened when I was setting a wrong range in one of the histograms. Maybe in that case the histogram had only overflows and underflows, and maybe then logz was failing or the axes were not drawn? After fixing the histogram range, it no longer crashed. But it could have been also just by chance…

In principle that’s just png’s… should be ok if the picture is generated.

I finally got a reproducible crash. The attached script crashes every time.

draw.cpp (3.7 KB)

I believe it has to do with a too large histogram size. I wonder why it fails silently without any warning.

If I divide the size (nChunks) by two, I get at least a warning:

Error in <TBufferFile::WriteByteCount>: bytecount too large (more than 1073741822)

If I do something inbetween, I get:

 *** Break *** segmentation violation
root.exe: malloc.c:2617: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.

So maybe related with: [RF] RooDataSet conversion to TTree fails for large datasets (bytecount too large) · Issue #12710 · root-project/root · GitHub

May by that’s for @moneta and/or @pcanal in that case.

Hello,

I think this a to due with the 1GB Buffer limit. This is a current limitation of the ROOT I/O. If your histogram is larger than 1GB you cannot store it directly in a file. You should use in that case a TTree and store the content of the histogram there

Lorenzo

1 Like

Is there a reason why there is no warning message if the size is too big? I was thinking that the theoretical size can be calculated in advance easily and printed.

I provided a PR solving this issue: [io] fix crash due to overflow in buffer length variable by ferdymercury · Pull Request #14627 · root-project/root · GitHub

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.