Root cern GUI & TThread: problems with TGTextView

Dear experts,

When I update TGTextView widget from slave thread after about 100 lines of text this widget works incorrect and I have
*** Break *** segmentation violation.

In slave thread I have this code:

    MyMainFrame *p = (MyMainFrame*)aPtr;

    while(1)
    {
        TThread::Lock();
        ostringstream osstr;
        osstr << p->twStatus_label->ReturnLineCount();
        p->twStatus_label->AddLine( osstr.str().c_str() );
        p->twStatus_label->ShowBottom();        
        TThread::UnLock();
        gSystem->Sleep(100);
    }

It is a small working project, which reproduce this problem.
code.tar.gz (1.3 KB)

To complile:

rootcint -f mainDic.cpp -c  mymainframe.h linkdef.h;
g++ -o main main.cpp mymainframe.cpp mainDic.cpp `root-config --cflags --glibs`;

P.S.
My root is

ROOT 5.34/36 (v5-34-36@v5-34-36, Apr 05 2016, 10:25:45 on linuxx8664gcc)

CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010

My OS is

NAME="Scientific Linux"
VERSION="7.3 (Nitrogen)"
ID="rhel"
ID_LIKE="fedora"
VERSION_ID="7.3"
PRETTY_NAME="Scientific Linux 7.3 (Nitrogen)"
ANSI_COLOR="0;31"
CPE_NAME="cpe:/o:scientificlinux:scientificlinux:7.3:GA"
HOME_URL="http://www.scientificlinux.org//"
BUG_REPORT_URL="mailto:scientific-linux-devel@listserv.fnal.gov"

REDHAT_BUGZILLA_PRODUCT="Scientific Linux 7"
REDHAT_BUGZILLA_PRODUCT_VERSION=7.3
REDHAT_SUPPORT_PRODUCT="Scientific Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="7.3"

Thank you in advance.

Hi,

As already said, all the GUI events have to be done in the main thread…

Cheers, Bertrand.

Dear Bertrand,
I absolutely agree with you and understand, that divide GUI in two threads is bad idea.
But could you explain how to send information from slave thread to master thread?
For example, something happened in slave thread and I want to show this information in my GUI using
TGTextView widget.

Try:

void *MyMainFrame::ReadoutLoop(void *aPtr)
{
    MyMainFrame *p = (MyMainFrame*)aPtr;
    while (1) {
        ostringstream osstr;
        osstr << gROOT->ProcessLine(Form("((TGTextView *)0x%lx)->ReturnLineCount();", (ULong_t)p->t
        gROOT->ProcessLine(Form("((TGTextView *)0x%lx)->AddLine(\"%s\");", (ULong_t)p->twStatus_lab
        gROOT->ProcessLine(Form("((TGTextView *)0x%lx)->ShowBottom();", (ULong_t)p->twStatus_label)
        gSystem->Sleep(100);
    }
}

Cheers, Bertrand

As I understand, you mean this (in your code i do not see line endings):

void *MyMainFrame::ReadoutLoop(void *aPtr)
{
    MyMainFrame *p = (MyMainFrame*)aPtr;
    while (1)
    {
        ostringstream osstr;
        osstr << gROOT->ProcessLine( Form("((TGTextView *)0x%lx)->ReturnLineCount();",
                                          (ULong_t)p->twStatus_label) );

        const char *s = osstr.str().c_str();

        gROOT->ProcessLine(Form ("((TGTextView *)0x%lx)->AddLine(\"%s\");",
                                 (ULong_t)p->twStatus_label, (ULong_t)s) );

        gROOT->ProcessLine(Form ("((TGTextView *)0x%lx)->ShowBottom();",
                                 (ULong_t)p->twStatus_label) );
        gSystem->Sleep(100);
    }
}

It works stable.
Could you explain where is magic?
If I understand may be I will not disturb you again and will solve similar problems myself.

Oh yes, sorry, here is the original:

void *MyMainFrame::ReadoutLoop(void *aPtr)
{
    MyMainFrame *p = (MyMainFrame*)aPtr;
    while (1) {
        ostringstream osstr;
        osstr << gROOT->ProcessLine(Form("((TGTextView *)0x%lx)->ReturnLineCount();", (ULong_t)p->twStatus_label));
        gROOT->ProcessLine(Form("((TGTextView *)0x%lx)->AddLine(\"%s\");", (ULong_t)p->twStatus_label, osstr.str().c_str()));
        gROOT->ProcessLine(Form("((TGTextView *)0x%lx)->ShowBottom();", (ULong_t)p->twStatus_label));
        gSystem->Sleep(100);
    }
}

It is simply because the gROOT->ProcessLine() calls are executed by the main thread.
And note also you should protect you code against concurrent events. For example, just destroy the window while the application is running…

Cheers, Bertrand.

1 Like

As I understand I should not use Lock / Unlock in while(1) in my case, because gROOT->ProcessLine will be in main thread.

If I close my app using cross in right top corner I will have *** Break *** segmentation violation.
Do you know how to avoid this (without Exit button)?
Should I send special signal?

You can do whatever you want inside the TGMainFrame::CloseWindow() method (if your class inherits from TGMainFrame), or use signal/slots, connecting to the TGMainFrame::CloseWindow() signal. Something like:

   Connect("CloseWindow()", "fMain", this, "CloseWindow()");
   fMain->DontCallClose();

Cheers, Bertrand.

Dear Bertrand,
Thanks for your help! :+1:

About CloseWindow: I think, may be we can discuss later in another topic.

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