App crashes when using root 5.34/18 (all ok in 5.34/05)

Hello,

I have recently updated my computer and encountered the problem, which didn’t appear with the previous version (still within v5.34) of root. I would be grateful if someone could point out an error in my code (I have shortened it as much as possible) or verify that something significant changed in root code, which makes my code obsolete.

As a background I use a makefile to compile my code into an executable, with root libraries linked in. I would like the program to do the following:

  • Create a set of canvases, fill them with some histos and save them as graphical files (pdf, png, etc…) without actually showing them on screen during program runtime.
  • At the very end of program’s execution I would like to start a TBrowser (or any graphical window like canvases, etc…) - This point causes the crash in new root versions.

test.cpp:

#include <iostream>
#include <TCanvas.h>
#include <TApplication.h>
#include <TBrowser.h>

using namespace std;

int main(int argc, char* argv[]){
	TCanvas* cvs;
	cvs = new TCanvas("a", "a", 1000, 700);
	// here: fill some histos, draw them on cvs and print it to pdf
	// without showing the canvas itself on screen

	TApplication theApp("App", &argc, argv);
		new TBrowser();  // <-- this is where program crashes
	theApp.SetIdleTimer(10000,"exit()"); // exit after 30 min of being idle
	theApp.SetReturnFromRun(true);
	theApp.Run();
}

makefile:

#---------------=============== ROOT  RELATED ===============---------------
ROOTCONFIG   := root-config

ARCH         := $(shell $(ROOTCONFIG) --arch)
PLATFORM     := $(shell $(ROOTCONFIG) --platform)
ALTCC        := $(shell $(ROOTCONFIG) --cc)
ALTCXX       := $(shell $(ROOTCONFIG) --cxx)
ALTF77       := $(shell $(ROOTCONFIG) --f77)
ALTLD        := $(shell $(ROOTCONFIG) --ld)

#CXX           =
ObjSuf        = o
SrcSuf        = cxx
ExeSuf        =
DllSuf        = so
OutPutOpt     = -o # keep whitespace after "-o"

ifeq (debug,$(findstring debug,$(ROOTBUILD)))
OPT           = -g
OPT2          = -g
else
ifneq ($(findstring debug, $(strip $(shell $(ROOTCONFIG) --config))),)
OPT           = -g
OPT2          = -g
else
OPT           = -O
OPT2          = -O2
endif
endif

ROOTCFLAGS   := $(shell $(ROOTCONFIG) --cflags)
ROOTLDFLAGS  := $(shell $(ROOTCONFIG) --ldflags)
ROOTLIBS     := $(shell $(ROOTCONFIG) --libs)
ROOTGLIBS    := $(shell $(ROOTCONFIG) --glibs)
HASTHREAD    := $(shell $(ROOTCONFIG) --has-thread)
ROOTDICTTYPE := $(shell $(ROOTCONFIG) --dicttype)
#NOSTUBS      := $(shell $(ROOTCONFIG) --nostubs)
ROOTCINT     := rootcint

# Stub Functions Generation
ifeq ($(NOSTUBS),yes)
   ROOTCINT = export CXXFLAGS="$(CXXFLAGS)"; $(ROOTSYS)/core/utils/src/rootcint_nostubs.sh -$(ROOTDICTTYPE)
endif

ifeq ($(ARCH),linuxx8664gcc)
# Linux with egcs, gcc 2.9x, gcc 3.x
CXX           = g++
CXXFLAGS      = $(OPT2) -Wall -fPIC
LD            = g++
LDFLAGS       = $(OPT2) -L/usr/local/lib -lnsl -lz -lm
SOFLAGS       = -shared
endif

CXXFLAGS     += $(ROOTCFLAGS)
LDFLAGS      += $(ROOTLDFLAGS)
LIBS          = $(ROOTLIBS) $(SYSLIBS)
GLIBS         = $(ROOTGLIBS) $(SYSLIBS)

ifneq ($(ALTCC),)
   CC  = $(ALTCC)
endif
ifneq ($(ALTCXX),)
   CXX = $(ALTCXX)
endif
ifneq ($(ALTF77),)
   F77 = $(ALTF77)
endif
ifneq ($(ALTLD),)
   LD  = $(ALTLD)
endif

ifneq ($(findstring g++, $(CXX)),)
GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f1)
GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d'.' -f2)
endif

CFLAGS	= -Wall -ggdb $(CXXFLAGS) $(LDFLAGS) $(ROOTCFLAGS) $(ROOTLDFLAGS) $(ROOTLIBS) $(ROOTGLIBS)
#---------------=============== ROOT  RELATED ===============---------------

#---------------=============== MAIN MAKEFILE ===============---------------
CC			= g++
TARGET		= test
SOURCE		= test.cpp
INCLUDE		= -I./ $(AN_INCLUDE_DIR)  
## end more includes

## Fix object destination to be ../obj relative to the src dir
OBJ=$(join $(addsuffix obj/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.o))) 

## Fix dependency destination to be ../.dep relative to the src dir
DEPENDS=$(join $(addsuffix .dep/, $(dir $(SOURCE))), $(notdir $(SOURCE:.cpp=.d)))

## Default rule executed
all:$(TARGET)
	@true

install:
	@echo "Installing binary in /bin folder"
	@-sudo cp test /bin

## Clean Rule
clean:
	@echo "Removing .o files"
	@-rm -f $(TARGET) $(OBJ) $(DEPENDS)
	@echo "Removing root dictionary files"
	@-rm -f $(ROOTDICT)
	@echo "Removing obj folders"
	@-rmdir obj
	@echo "Removing .dep folders"
	@-rmdir .dep

## Rule for making the actual target
$(TARGET): $(OBJ)
	@echo "============="
	@echo "Linking the target $@"
	@echo "============="
	@echo $(CC) $(CFLAGS) -o $@ $^ $(LIBS)
	@$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
	@echo -- Link finished --

## Generic compilation rule
#%.o : %.cpp
#	@mkdir -p $(dir $@)
#	@echo "============="
#	@echo "Compiling $<"
#	@$(CC) $(CFLAGS) -c $< -o $@


## Rules for object files from cpp files
## Object file for each file is put in obj directory
obj/%.o : %.cpp
	@mkdir -p $(dir $@)
	@echo "============="
	@echo "Compiling $<"
	@$(CC) $(CFLAGS) -c $< -o $@

## Make dependancy rules
.dep/%.d: %.cpp
	@mkdir -p $(dir $@)
	@echo "============="
	@echo Building dependencies file for $*.o
	@$(SHELL) -ec '$(CC) -M $(CFLAGS) $< | sed "s^$*.o^obj/$*.o^" > $@'

## Make root dictionary
$(ROOTDICT): $(ROOTDICTSRC)
	@echo "============="
	@echo "Generating dictionary $<"
	$(ROOTCINT) -f $(ROOTDICT) -c $(ROOTDICTSRC)

## Include the dependency files
-include $(DEPENDS)
#---------------=============== MAIN MAKEFILE ===============---------------

I have tested this program on the following platforms:
ROOT_RELEASE “5.34/01”, Linux Mint 13 - works OK
ROOT_RELEASE “5.34/05”, Ubuntu 12.04.5 - works OK
ROOT_RELEASE “5.34/18”, Ubuntu 12.04.4 - crashes
ROOT_RELEASE “5.34/18”, Scientific Linux CERN SLC release 6.5 - crashes
ROOT_RELEASE “5.34/19”, Red Hat Enterprise Linux Server release 6.5 - crashes
ROOT_RELEASE “5.34/20”, Ubuntu 14.04.1 - crashes

I don’t have a quick access to any machines running root version between “5.34/05” and “5.34/18”, but to me it seems quite probable the problem originates in one of them…

Hi,

did you re-compile your program with the newer root version or just re-executed once replacing the root installation?

Cheers,
Danilo

Hi,

I have recompiled the code every time it was moved to a different machine. In fact when testing it on different platforms I copied only the code, not the binaries, to make sure I really run a locally compiled version.

Hi,

thanks for reporting.
I can reproduce the problem even on OSx, root5 and root6.
I opened a ticket for our gui experts: it seems that a global variable is not properly initialised when creating the TBrowser: sft.its.cern.ch/jira/browse/ROOT-6784

Cheers,
Danilo

Hi,

As mentioned in Jira, the problem is that when creating a TCanvas, if there is no gApplication, a default one is created. Then, when creating the real one, the default one is deleted, and its destructor calls gROOT->EndOfProcessCleanups(), which is deleting many things, including gStyle. So indeed this should be protected, but the TApplication instance should be created before any TCanvas (it should even be the first thing to create in a standalone application…)

Cheers, Bertrand.