TCanvas crash in GUI

From: Tom Roberts <tjrob_at_fnal.gov>
Date: Tue, 28 Aug 2007 20:26:27 -0500


The attached program will regularly crash on Linux, and will hang at the same place in Windows (burning CPU time); it works fine in Mac OS X (Intel).

To run it, save it to some directory and do:

        root test.C
It will pop up a small dialog box -- move it away from where new windows are created. Then push "Create Plot" three times, which will create three plot windows on top of each other. Move the "Plot 3" window down a bit and close the "Plot 2" window (via the usual window control). Then close the "Plot 3" window, leaving "Plot 1" open. Now push "Create Plot" and watch the crash or hang. It takes a complicated sequence of window opens and closes to trigger the crash, and this is the simplest I have found (if it didn't crash yet, do a ".q" to see one [not on Mac OS X]).

On Linux the output is:


FreeType Engine v2.1.9 used to render TrueType fonts. Compiled on 11 July 2006 for linux with thread support.

CINT/ROOT C/C++ Interpreter version 5.16.13, June 8, 2006 Type ? for help. Commands must be C++ statements. Enclose multiple statements between { }. root [0]
Processing test.C...
root [1] Plot() creating new TCanvas name='Plot1'

Plot()  OK
Plot() creating new TCanvas  name='Plot2'
Plot()  OK
Plot() creating new TCanvas  name='Plot3'
Plot()  OK
plotClosed(Plot2)
plotClosed(Plot2)
plotClosed(Plot2)
plotClosed(Plot3)

plotClosed(Plot3)
plotClosed(Plot3)
Plot() creating new TCanvas name='Plot4'

That trace gives a hint that this is related to the editor. If I comment out line 90 [gEnv->SetValue("Canvas.ShowEditor",1);] it now seems to work fine on all 3 OSs.

Note the three calls to plotClosed() are worrisome (only 2 on Windows and Mac OS). I do not know if that is related to this problem or not. It's also curious that the histogram looks the same on Windows and Mac OS X, but is different on Linux (even when Windows and Linux are running on VMs under VMware/Mac, so this is not the CPU).

This is using Root 5.12. On Linux, root 5.16 did not crash for the above sequence, but did crash on an immediately following ".q" (!); a much more complicated sequence of "Create Plot" and close window did elicit a crash as above. My primary application is linked with 5.12 so that is the version I normally use.

Tom Roberts

// test.C

#include <TGClient.h> // force Root to load libGui.

/** class Plot is a single plot
 **/
class Plot {

	RQ_OBJECT("Plot")
	char name[16];
	TNtuple *ntuple;
	TCanvas *canvas;
	TH1D *th1d;
	static int number;
public:
	/// Constructor.
	Plot(TNtuple *_ntuple);

	/// Destructor.
	virtual ~Plot();

	/// plotClosed() is connected to CloseWindow() of Plot window.
	void plotClosed() {
		printf("plotClosed(%s)\n",name);
	}

};
int Plot::number=0;

Plot::Plot(TNtuple *_ntuple)
{

	sprintf(name,"Plot%d",++number);
	ntuple = _ntuple;
	canvas = 0;
	th1d = 0;

	// draw the plot in its own window (canvas)
printf("Plot() creating new TCanvas  name='%s'\n",name); fflush(stdout);
	canvas = new TCanvas(name,name);
printf("Plot()  OK\n"); fflush(stdout);
	canvas->SetFolder(true);
	canvas->Connect("Closed()","Plot",this,"plotClosed()");
	th1d = new TH1D(name,name,100,0.0,1.0);
	// a very simple filling of the histogram
	int n=100;
	for(int i=0; i<n; ++i) {
		double x=(double)i/(double)n;
		th1d->Fill(x);
	}
	th1d->Draw("");
	canvas->Selected(canvas,canvas->FindObject(th1d),1);
}

Plot::~Plot()
{

	if(canvas) canvas->Disconnect();
	// cannot delete canvas, because closing the window already did that
	canvas = 0;

}

/** class Test is a test window for opening/closing Plot windows.  **/
class Test {

        RQ_OBJECT("Test")
private:

        TGMainFrame *window;
public:

	/// Constructor (defaults work fine)
	Test(const TGWindow *win=0, UInt_t width=0, UInt_t height=0);

	/// Destructor.
	virtual ~Test();

	/// command() is Connect-ed to all of the signals
	static void command(Int_t);

};
void Test::command(Int_t id)
{
	switch(id) {
	case 50:
		new Plot(0);
		break;
	case 99:
		gApplication->Terminate(0);
	}

}

Test::Test(const TGWindow *win, UInt_t width, UInt_t height) {

	// have all new canvases show the editor initially.
	gEnv->SetValue("Canvas.ShowEditor",1);

	if(win == 0) win = gClient->GetRoot();
	if(width <= 0) width = 200;
	if(height <= 0) height = 200;
	window = new TGMainFrame(win,width,height,kVerticalFrame);

	// Layout the main Test window
	TGTextButton *create = new TGTextButton(window,"Create Plot",50);
	window->AddFrame(create,new TGLayoutHints(kLHintsCenterX,20,20,20,20));
	create->SetCommand("Test::command(50)");

	// display window
	window->Connect("CloseWindow()","Test",this,"command(=99)");
	window->Layout();
	window->SetWindowName("Test");
	window->MapSubwindows();
	window->Resize(window->GetDefaultSize());
	window->MapWindow();

}

Test::~Test()
{

	if(!window) return;
	window->Cleanup();
	// cannot delete window, as closing it already did that
	window = 0;

}

// Root has problems with the default optimization level ".O 4" void test() { gROOT->ProcessLine(".O 3"); new Test(); } Received on Wed Aug 29 2007 - 03:41:10 CEST

This archive was generated by hypermail 2.2.0 : Wed Aug 29 2007 - 11:50:01 CEST