You are not logged in.

Dear visitor, welcome to QtForum.org. If this is your first visit here, please read the Help. It explains in detail how this page works. To use all features of this page, you should consider registering. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

1

Monday, February 18th 2013, 2:15pm

Crash within Qt Code using drag and drop (Qt BUG?)

Hi, I'm posting this in this forum to see if I can get any more help as this is driving me crazy
http://qt-project.org/forums/viewthread/24927/



Hi, I have an intermittent crash within the Qt Code. I have run it with the Qt sources and the crash occurs on: Line 1273 of qcoreapplication.cpp.
It is due to a de-referenced pointer.



  1. void QCoreApplication::postEvent(QObject *receiver, QEvent *event, int priority)

  2. {

  3. if (receiver == 0) {

  4. qWarning("QCoreApplication::postEvent: Unexpected null receiver");

  5. delete event;

  6. return;

  7. }

  8. QThreadData * volatile * pdata = &receiver->d_func()->threadData;

  9. QThreadData *data = *pdata; <===================================== CRASH HERE

  10. if (!data) {

  11. // posting during destruction? just delete the event to prevent a leak

  12. delete event;

  13. return;

  14. }

  15. // lock the post event mutex

  16. data->postEventList.mutex.lock();

  17. // if object has moved to another thread, follow it

  18. while (data != *pdata) {

  19. data->postEventList.mutex.unlock();

This is within the drag->exec() function, however looks like it may be due to Qt posting application events.
For more information please see the thread on stack overflow:
http://stackoverflow.com/questions/14856…-dropping-in-qt
The drag and drop code is quite long and covers a lot of possibilities. But essentially I am moving widgets about yes. I have two drop-able containers, one accepts one type of widget (A), the other takes another type (which is the container for the first type) (B).
The first type (A) requires the newly created widget to be deleted if it is generated from the side bar menu or not if it is dragged from the container (B).
The second type (B) requires the widget to be deleted if dragged from the sidebar, or not if dragged from the second type of droppable container.
Its fairly complex but all works as it should. The intermittent bug occurs rarely but I have written some code to make the mouse move around dragging and dropping which speeds up its occurrence (It still can be replicated without).
I will post up the stack trace from the bottom up (bottom level shown above):
qdnd_x11.cpp



  1. void QX11Data::xdndHandleFinished(QWidget *, const XEvent * xe, bool passive)

  2. {

  3. DEBUG("xdndHandleFinished");

  4. const unsigned long *l = (const unsigned long *)xe->xclient.data.l;

  5. DNDDEBUG << "xdndHandleFinished, l[0]" << l[0]

  6. << "qt_xdnd_current_target" << qt_xdnd_current_target

  7. << "qt_xdnd_current_proxy_targe" << qt_xdnd_current_proxy_target;

  8. if (l[0]) {

  9. int at = findXdndDropTransactionByWindow(l[0]);

  10. if (at != -1) {

  11. restartXdndDropExpiryTimer();

  12. QXdndDropTransaction t = X11->dndDropTransactions.takeAt(at);

  13. QDragManager *manager = QDragManager::self();

  14. Window target = qt_xdnd_current_target;

  15. Window proxy_target = qt_xdnd_current_proxy_target;

  16. QWidget *embedding_widget = current_embedding_widget;

  17. QDrag *currentObject = manager->object;

  18. qt_xdnd_current_target = t.target;

  19. qt_xdnd_current_proxy_target = t.proxy_target;

  20. current_embedding_widget = t.embedding_widget;

  21. manager->object = t.object;

  22. if (!passive)

  23. (void) checkEmbedded(qt_xdnd_current_widget, xe);

  24. current_embedding_widget = 0;

  25. qt_xdnd_current_target = 0;

  26. qt_xdnd_current_proxy_target = 0;

  27. if (t.object)

  28. t.object->deleteLater(); <========================

  29. qt_xdnd_current_target = target;

  30. qt_xdnd_current_proxy_target = proxy_target;

  31. current_embedding_widget = embedding_widget;

  32. manager->object = currentObject;

  33. }

  34. }

  35. waiting_for_status = false;

  36. }

qapplication_x11.cpp



  1. X11->xdndHandleLeave(widget, event, passive_only);

  2. } else if (event->xclient.message_type == ATOM(XdndDrop)) {

  3. X11->xdndHandleDrop(widget, event, passive_only);

  4. } else if (event->xclient.message_type == ATOM(XdndFinished)) {

  5. X11->xdndHandleFinished(widget, event, passive_only); <============

  6. } else {

  7. if (passive_only) return 0;

  8. // All other are interactions

  9. }

qapplication_x11.cpp



  1. case ClientMessage: // client message

  2. return x11ClientMessage(widget,event,False); <============

qguieventdispatcher_glib.cpp



  1. // send through event filter

  2. if (source->q->filterEvent(&event))

  3. continue;

  4. if (qApp->x11ProcessEvent(&event) == 1) <============

  5. return true;

  6. if (event.xany.serial >= marker)

  7. goto out;

  8. } while (XEventsQueued(X11->display, QueuedAfterFlush));

  9. out:

Since I have only been debugging with the Qt source today, I have seen it happens in more than one location in the function above.….
It seems to me to be the data pointer becomes invalid, if I could find out what this is then I would be able to trace it back, however, it is obtained from
QThreadData * volatile * pdata = &receiver->d_func()->threadData;and d_func() doesn’t seem accessible from the source I have.



  1. }

  2. QThreadData * volatile * pdata = &receiver->d_func()->threadData;

  3. QThreadData *data = *pdata;

  4. if (!data) {

  5. // posting during destruction? just delete the event to prevent a leak

  6. delete event;

  7. return;

  8. }

  9. // lock the post event mutex

  10. data->postEventList.mutex.lock();

  11. // if object has moved to another thread, follow it

  12. while (data != *pdata) {

  13. data->postEventList.mutex.unlock(); <============= CRASH CAN ALSO HAPPEN HERE

  14. data = *pdata;

  15. if (!data) {

  16. // posting during destruction? just delete the event to prevent a leak

  17. delete event;

  18. return;