PDA

View Full Version : QApplication::exec crashing while running a multithreaded application



psadhukhan
24th November 2008, 07:20
Hi,

I am new to Qt world. I am using Qt4.4.3 on linux/X11 system and I have taken the opensource Qt/X11 version
I had a product which was running in Qt3.3 and I am trying to port it to Qt4. I have modified so as of now it does not give any compilation error in Qt4. But, while trying to run the application, I am getting SEGV and the gdb shows the problem emantes from exec() call
I also tried with debug version of qt but same result.
Here's what I see in gdb

QtApplication::exec()

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 107215760 (LWP 7346)]
0x06f107be in QString::fromLocal8Bit (
str=0x2d322e31 <Address 0x2d322e31 out of bounds>, size=-1)
at tools/qstring.cpp:3363
3363 if (size == 0 || (!*str && size < 0))
Current language: auto; currently c++
(gdb) bt
#0 0x06f107be in QString::fromLocal8Bit (
str=0x2d322e31 <Address 0x2d322e31 out of bounds>, size=-1)
at tools/qstring.cpp:3363
#1 0x06fcca12 in QCoreApplication::arguments ()
at kernel/qcoreapplication.cpp:1849
#2 0x053a5e95 in sm_performSaveYourself (smd=0x87467e8)
at kernel/qapplication_x11.cpp:5078
#3 0x053a683b in sm_saveYourselfCallback (smcConn=0x8747460,
clientData=0x87467e8, saveType=1, shutdown=0, interactStyle=0)
at kernel/qapplication_x11.cpp:5061
#4 0x004b351f in _SmcProcessMessage () from /usr/lib/libSM.so.6
#5 0x004c90a9 in IceProcessMessages () from /usr/lib/libICE.so.6
#6 0x053a693e in QSmSocketReceiver::socketActivated (this=0x8749710)
at kernel/qapplication_x11.cpp:5200
#7 0x053a69af in QSmSocketReceiver::qt_metacall (this=0x8749710,
_c=QMetaObject::InvokeMetaMethod, _id=0, _a=0x663e920)
at .moc/debug-shared/qapplication_x11.moc:64
#8 0x06fe5507 in QMetaObject::activate (sender=0x87475a0,
from_signal_index=4, to_signal_index=4, argv=0x663e920)
at kernel/qobject.cpp:3022
#9 0x06fe5a91 in QMetaObject::activate (sender=0x87475a0, m=0x70d4a50,
local_signal_index=0, argv=0x663e920) at kernel/qobject.cpp:3092
#10 0x0702ece0 in QSocketNotifier::activated (this=0x87475a0, _t1=12)
---Type <return> to continue, or q <return> to quit---
at .moc/debug-shared/moc_qsocketnotifier.cpp:81
#11 0x06ff0709 in QSocketNotifier::event (this=0x87475a0, e=0x663ee3c)
at kernel/qsocketnotifier.cpp:320
#12 0x0532acff in QApplicationPrivate::notify_helper (this=0x8700038,
receiver=0x87475a0, e=0x663ee3c) at kernel/qapplication.cpp:3803
#13 0x0532b018 in QApplication::notify (this=0x871c6c0, receiver=0x87475a0,
e=0x663ee3c) at kernel/qapplication.cpp:3393
#14 0x06fce669 in QCoreApplication::notifyInternal (this=0x871c6c0,
receiver=0x87475a0, event=0x663ee3c) at kernel/qcoreapplication.cpp:587
#15 0x06fd2c93 in QCoreApplication::sendEvent (receiver=0x87475a0,
event=0x663ee3c)
at ../../include/QtCore/../../src/corelib/kernel/qcoreapplication.h:209
#16 0x07003dce in socketNotifierSourceDispatch (source=0x872ceb8)
at kernel/qeventdispatcher_glib.cpp:105
#17 0x004147f2 in g_main_context_dispatch () from /lib/libglib-2.0.so.0
#18 0x004177cf in ?? () from /lib/libglib-2.0.so.0
#19 0x00417d35 in g_main_context_iteration () from /lib/libglib-2.0.so.0
#20 0x07003578 in QEventDispatcherGlib::processEvents (this=0x86fc458,
flags=@0x663ef8c) at kernel/qeventdispatcher_glib.cpp:319
#21 0x053e7b58 in QGuiEventDispatcherGlib::processEvents (this=0x86fc458,
flags=@0x663efbc) at kernel/qguieventdispatcher_glib.cpp:198
#22 0x06fcab5e in QEventLoop::processEvents (this=0x663f040, flags=@0x663eff8)
at kernel/qeventloop.cpp:143
---Type <return> to continue, or q <return> to quit---
#23 0x06fcad9d in QEventLoop::exec (this=0x663f040, flags=@0x663f048)
at kernel/qeventloop.cpp:194
#24 0x06fcefa0 in QCoreApplication::exec () at kernel/qcoreapplication.cpp:845
#25 0x0532a9fc in QApplication::exec () at kernel/qapplication.cpp:3331
#26 0x003bfaf4 in QtApplication::exec (this=0x871c6c0)
at ../../src/share/basis/native/awt/qt/QtApplication.cpp:75
#27 0x003be6c0 in Java_java_awt_QtGraphicsEnvironment_QTexec (env=0x87244fc,
self=0x870dacc) at ../../src/share/basis/native/awt/qt/QtBackEnd.cpp:975
#28 0x08154364 in args_done ()
at ../../src/x86/javavm/runtime/invokeNative_i386.S:201
#29 0x087244fc in ?? ()
#30 0x0870dacc in ?? ()
#31 0x082e8080 in ?? ()
#32 0x0870dad0 in ?? ()
#33 0x087244fc in ?? ()
#34 0x0663f118 in ?? ()
#35 0x080b024c in CVMinvokeJNIHelper (ee=0x87244fc, mb=0x3be690)
at ../../src/share/javavm/runtime/interpreter.c:4329
Backtrace stopped: frame did not save the PC

Here's what I do before exec()
1. I create QApplication(argc, argv) where argc = 1, argv={"cvm", "-qws", NULL}; //where qws was used for embedded qt but since I use the product in Qt/X11 I use argc=1 so qws will not be passed
The code is like this:

bool
QtScreen::init()
{
printf("QtScreen::init()\n");
if ( qtApp != NULL )
return TRUE; // already initialized

/*
* We need to create an array of size 3 because the QApplication assigns a
* NULL pointer to the argv[argc] position after it processes and removes
* all the Qt command line options from the argv vector. This is a Qt bug
* to write past the end of the argv vector. Qt also keeps a refernece
* to argv,
* so it shouldn't go away.
*/

int argc = 1;
char ** argv = this->getArgs(&argc);

/*
* Create a QApplication
*/
new QtApplication(argc, argv);
QRect screen_bounds = QApplication::desktop()->frameGeometry();
/*
* Create the Qt widget that backs the Window
*/
printf("createQtWindow called\n");
this->createQtWindow();
assert(this->m_window != NULL);

AWT_QT_LOCK;
#ifdef QT_VER_4
qtApp->setActiveWindow(this->m_window);
#else
qtApp->setMainWidget(this->m_window);
#endif

AWT_QT_UNLOCK;

return TRUE ;
}

QtScreen::getArgs(int *argc) {
printf("QtScreen::getArgs()\n");
int count;
// Use the "-sync" flag to force Xlib calls to be synchronous, which
// would aid in debugging Xlib async errors.

static char *argv[] = {"cvm", "-qws", NULL};

count = 1;

#ifdef QWS
#ifndef QTOPIA
// If environment varible QWS_CLIENT is not defined,
// assume we are running as the server (in the qt-embedded sense).
if (getenv("QWS_CLIENT") == NULL) {
count++;
}
#endif /* QTOPIA */
#endif /* QWS */

*argc = count;

return (char **)&argv;
}

void
QtScreen::createQtWindow() {
printf("QtScreen::createQtWindow()\n");
AWT_QT_LOCK;
this->m_window = new QtWindow(Qt::FramelessWindowHint|Qt::Window);
QBitmap bitmap(this->m_width, this->m_height);
AWT_QT_UNLOCK;
this->m_window->setMask(bitmap);
}

#ifdef QT_VER_4
QtWindow::QtWindow(int flags, const char *name, QWidget *parent) :
QWidget( parent, (Qt::WindowFlags)flags)
#else
QtWindow::QtWindow(int flags, const char *name, QWidget *parent) :
QWidget( parent, name, (WFlags)flags)
#endif
{
printf("QtWindow::QtWindow %d %s, %u\n", flags, name,parent);
// install event filter...?
// If mouse tracking is true, then mouseMoveEvent is called
// whenever the mouse moved, even if button isn't held down.
//AWT_QT_LOCK;
setMouseTracking(TRUE);
//AWT_QT_UNLOCK;
transMask = NULL;
printf("QtWindow constructor returned\n");
}

Once init() calls returns, we call exec() as in
int
QtApplication::exec(void) {
printf("QtApplication::exec()\n");
#if 0 // 6207033
printf("*** QtApplication.exec(tid=%x) ***\n",
(int)AWT_QT_CURRENT_THREAD()) ;
#endif
m_is_event_loop_started = TRUE ;
int ret = NORMAL_EXIT_CODE;

#ifdef QT_THREAD_SUPPORT
ret = QAPPLICATION_CLASS::exec() ;
printf("exec done\n");
#else
printf("QtApplication::QtApplication() no QT_THREAD_SUPPORT\n");
QtCondVar timer ;
timer.mutex()->lock();
while ( !m_shutdown ) { // 6176847:Loop till we shutdown.
AWT_QT_LOCK;
this->processEvents(0);
AWT_QT_UNLOCK;
/* sleep for some time */
timer.wait(100) ;
}
// 6176847: set the return code to simulate the same behavior as
// exec() return value.
ret = SHUTDOWN_EXIT_CODE;
#endif /* QT_THREAD_SUPPORT */

We have QT_THREAD_SUPPORT defined
Cananyone please help me? I am stuck with this problem

high_flyer
24th November 2008, 10:02
From the segmentation fault output, it can be seen that the crash is in the function
sm_performSaveYourself(), which seems to be a call back function.
(and the offending variable is probably a QString)

The fact QApplication::exec() is where you see the crash is simply because everything happens in QApplication::exec().

Modifying code so that it compiles is no guarantee that it will run.
Qt3 and Qt4 are substantially different - and even more so when it comes to threads.
My guess is that you have a problem with thread affinity.
But that is only a guess.

psadhukhan
24th November 2008, 10:23
Thanks.
Can you please tell me what I need to check corresponding to threads.
Since the product was working perfectly fine in Qt3.x( I have verified that) I am at a loss as to what I need to check.
Sometimes I get in Qt4 (which I did not get in Qt3]
QPixmap:it is not safe to use pixmap outside GUI thread, so it probably points to some threading issue

One thing I wanted to notify is, we were also using QApplication::lock() in our code but since Qt4 has made QApplication::lock() obsolete, I used QMutex mutex(QMutex::Recursive) [lock/unlock] function
The reason for using Recursive was sometimes the code has a lock inside a lock [and as told was working in Qt3]

LOCK: //QApplication::lock
funcA();
UNLOCK;

funcA(){
LOCK:
...
UNLOCK:

high_flyer
24th November 2008, 10:31
Unfortunately its not something anyone who does not know the code can answer.
You have to read the Qt documentation in respect to the changes done between Qt3 and Qt4.
Threading was redone extensively in Qt4, and you really should read the threading section in Qt4 docs.
When you know how threading in Qt4 works, you might attempt to rewrite the old Qt3 code so that it will conform to Qt4.
http://doc.trolltech.com/4.4/threads.html

I also would think, you should not hope to finish such a task in one afternoon, for a "real" application.

psadhukhan
1st December 2008, 12:13
I have taken a look at the threading tutorial but I don't think I am doing anything that is prohibited.
Since the product follows a Java multithreaded AWT model, whereby the main AWT Java thread [actually linux posix thread as I am testing in linux-x86] is what will be making GUI calls and then there is an eventThread [another Java thread] which will initialize [create QApplication, does show() and exec()]. The main AWT thread will draw in the QImage backbuffer and the paintEvent() call will flush the QImage into QPaintDevice. This is the logic that I wanted to follow in Qt4
But, in Qt4 calls I am not sure why I am getting the crash as described above as soon as I call exec(). sm_performSaveYourself is a QT function which I don't have control on and so I am not sure why it will create a QString with wrong address [thereby creating segv]. Also, libSM.so and libICE.so are system lib I presume so there also I do not have a control

I also have checked my mutex logic. I am using QMutex and I have seen that if I use it wrongly, it shows deadlock from QMutex class. But I am not seeing any such problem in our product. Is there anyone who has seen this kind of crash and know about a possible solution or an area where to investigate?
I can send the code to anyone who is interested.
I am really stuck with this crash. PLease suggest some remedy