eteran / nedit-ng

a Qt5 port of the NEdit using modern C++14
GNU General Public License v2.0
95 stars 26 forks source link

crash with commit 16cb9a5a #135

Closed marilmanen closed 4 years ago

marilmanen commented 4 years ago

Unfortunately, I still get crashes (almost every day). Here is a stack trace just in case you can see some clue in it. I have tried to follow what I'm doing when a crash occurs, but at the moment I have no idea what is causing these.

#0  0x00000000005751b3 in gap_buffer<char, std::char_traits<char> >::operator[](long) const (this=this@entry=0x2b65100, n=n@entry=0) at /tmp/nedit-ng/src/gap_buffer.h:132
#1  0x0000000000575948 in BasicTextBuffer<char, std::char_traits<char> >::searchForward(BasicTextCursor<int>, char) const (this=this@entry=0x2b650f0, startPos=..., searchChar=searchChar@entry=10 '\n') at /tmp/nedit-ng/src/TextBuffer.tcc:1154
#2  0x000000000057599a in BasicTextBuffer<char, std::char_traits<char> >::BufEndOfLine(BasicTextCursor<int>) const (this=this@entry=0x2b650f0, pos=...)
    at /tmp/nedit-ng/src/TextBuffer.tcc:810
#3  0x00000000005784b0 in BasicTextBuffer<char, std::char_traits<char> >::BufGetTextInRect(BasicTextCursor<int>, BasicTextCursor<int>, long, long) const (this=0x2b650f0, start=..., end=..., rectStart=0, rectEnd=46002112) at /tmp/nedit-ng/src/TextBuffer.tcc:500
#4  0x0000000000578842 in BasicTextBuffer<char, std::char_traits<char> >::getSelectionText(BasicTextBuffer<char, std::char_traits<char> >::Selection const*) const (this=<optimized out>, sel=<optimized out>) at /tmp/nedit-ng/src/TextBuffer.tcc:1203
#5  0x00000000005788a0 in BasicTextBuffer<char, std::char_traits<char> >::BufGetSelectionText() const (this=<optimized out>) at /tmp/nedit-ng/src/TextBuffer.tcc:645
#6  0x00000000005738a1 in TextAreaMimeData::retrieveData(QString const&, QVariant::Type) const (this=0x2a0de60, mimeType=..., type=QVariant::ByteArray)
    at /tmp/nedit-ng/src/TextAreaMimeData.cpp:23
#7  0x00002b3bcb6f3676 in QMimeDataPrivate::retrieveTypedData(QString const&, QVariant::Type) const () at /lib64/libQt5Core.so.5
#8  0x00002b3bcb6f488d in QMimeData::data(QString const&) const () at /lib64/libQt5Core.so.5
#9  0x00002b3bcb0d80f6 in QInternalMimeData::renderDataHelper(QString const&, QMimeData const*) () at /lib64/libQt5Gui.so.5
#10 0x00002b3bd3a7e5ff in QXcbMime::mimeDataForAtom(QXcbConnection*, unsigned int, QMimeData*, QByteArray*, unsigned int*, int*) () at /lib64/libQt5XcbQpa.so.5
#11 0x00002b3bd3a6ea35 in QXcbClipboard::sendSelection(QMimeData*, unsigned int, unsigned int, unsigned int) () at /lib64/libQt5XcbQpa.so.5
#12 0x00002b3bd3a6f1c5 in QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t*) () at /lib64/libQt5XcbQpa.so.5
#13 0x00002b3bd3a7631e in QXcbConnection::handleXcbEvent(xcb_generic_event_t*) () at /lib64/libQt5XcbQpa.so.5
#14 0x00002b3bd3a7819e in QXcbConnection::processXcbEvents() () at /lib64/libQt5XcbQpa.so.5
#15 0x00002b3bcb6fa1de in QObject::event(QEvent*) () at /lib64/libQt5Core.so.5
#16 0x00002b3bcaab7d8c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#17 0x00002b3bcaabef68 in QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#18 0x00002b3bcb6d0be6 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib64/libQt5Core.so.5
#19 0x00002b3bcb6d3503 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () at /lib64/libQt5Core.so.5
#20 0x00002b3bcb71fab3 in postEventSourceDispatch(_GSource*, int (*)(void*), void*) () at /lib64/libQt5Core.so.5
#21 0x00002b3bcffd6099 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#22 0x00002b3bcffd63f8 in g_main_context_iterate.isra.19 () at /lib64/libglib-2.0.so.0
#23 0x00002b3bcffd64ac in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#24 0x00002b3bcb71f45c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib64/libQt5Core.so.5
#25 0x00002b3bcb6cf6db in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib64/libQt5Core.so.5
#26 0x00002b3bcb6d7c04 in QCoreApplication::exec() () at /lib64/libQt5Core.so.5
#27 0x0000000000488955 in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at /tmp/nedit-ng/src/nedit.cpp:126
eteran commented 4 years ago

That looks like maybe a copy and paste operation with the middle click? Strange! I'll see what I can figure out :-(.

marilmanen commented 4 years ago

I can't say for sure, but I think it happens at the time when new text is updated to the copy/paste buffers, either by selecting text in Linux terminal (or any other application than nedit-ng in Linux), or when copying text in Linux or in the Windows side (Linux running in the NXClient). The crash seems to happen when I'm not actively working with nedit-ng window.

eteran commented 4 years ago

Unfortunately, it is REALLY hard to make sense of this error.

From the stack trace, it looks like it is crashing while trying to read from the gap buffer "out of bounds"... but the index it is trying to read is literally 0. The buffer is never "zero bytes big", so there should always be something there.

The only thing I can think of is if somehow the underlying buffer that the mime event is trying to refer to has somehow been deleted out from under it. But I have a hard time imagining how that could happen :-/.

I'll continue to debug the problem, I do suspect that it has something to do with with your unusual environment possibly that it is sending selection messages to widgets that have been deleted? I dunno.

Either way, it would be nice if nedit-ng handled these types of things gracefully! I have some thoughts on how to take a slightly different strategy for this feature, so we'll see what I come up with.

eteran commented 4 years ago

OK! I think I have figured out the root of the problem!! It may be complicated to fix (we'll see once I dive it). But I can reliably reproduce the issue with the following steps:

  1. open two documents
  2. highlight some text in either document
  3. close the tab which has the highlighted text
  4. middle-click in any other application
  5. Crash!

The issue is that when we create a selection, we don't want to actually copy the data yet, because buffers can be huge and there are tons of selections that don't lead to a paste. So we create an object on the heap, which basically just has a reference to the buffer in which the selection occurred in. When a paste occurs, we just ask the buffer that that object refers to and says "give me your selected data".

It's a lazy copy of sorts.

The problem is that the underlying buffer may get deleted before the paste operation, so the selection object (TextAreaMimeData) is referring to dead data. So it crashes.

I have thoughts about how to address this, but it may take a bit to come up with the ideal solution.

Thanks for sticking with me while I figure this out!

eteran commented 4 years ago

There is an attempted fix in master. I can no longer replicate the issue with it in place. Please see if this fixes the problem for you.

marilmanen commented 4 years ago

Great. Latest version is now in use, so hopefully you will not hear from me anymore :-)

marilmanen commented 4 years ago

Unfortunately it's me again. Here is a new stack trace, there seems to be still some issue with the buffer. This time the crash happened when I closed one of my tab windows.

#0  0x00002ad03e3d5426 in __memcpy_ssse3_back () at /lib64/libc.so.6
#1  0x00002ad03db1e1bb in std::string::_M_replace_safe(unsigned long, unsigned long, char const*, unsigned long) () at /lib64/libstdc++.so.6
#2  0x00002ad03db1f3df in std::string::replace(unsigned long, unsigned long, char const*, unsigned long) () at /lib64/libstdc++.so.6
#3  0x0000000000575a53 in gap_buffer<char, std::char_traits<char> >::to_string(long, long) const (__k2=<optimized out>, __k1=<optimized out>, __i2=..., __i1=..., this=0x7ffe6978b110)
    at /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/basic_string.h:4207
#4  0x0000000000575a53 in gap_buffer<char, std::char_traits<char> >::to_string(long, long) const (__last=<optimized out>, __first=<optimized out>, this=0x7ffe6978b110)
    at /opt/rh/devtoolset-6/root/usr/include/c++/6.3.1/bits/basic_string.h:3606
#5  0x0000000000575a53 in gap_buffer<char, std::char_traits<char> >::to_string(long, long) const (this=this@entry=0x3409a20, start=3407904, end=3604535)
    at /tmp/nedit-ng/src/gap_buffer.h:265
#6  0x0000000000575ab8 in BasicTextBuffer<char, std::char_traits<char> >::BufGetRange(BasicTextCursor<int>, BasicTextCursor<int>) const (this=0x3409a10, start=..., end=...)
    at /tmp/nedit-ng/src/TextBuffer.tcc:102
#7  0x00000000005786fa in BasicTextBuffer<char, std::char_traits<char> >::getSelectionText(BasicTextBuffer<char, std::char_traits<char> >::Selection const*) const (this=<optimized out>, sel=<optimized out>) at /tmp/nedit-ng/src/TextBuffer.tcc:1221
#8  0x0000000000578770 in BasicTextBuffer<char, std::char_traits<char> >::BufGetSelectionText() const (this=<optimized out>) at /tmp/nedit-ng/src/TextBuffer.tcc:661
#9  0x0000000000573631 in TextAreaMimeData::retrieveData(QString const&, QVariant::Type) const (this=0x34ba360, mimeType=..., type=QVariant::ByteArray)
    at /tmp/nedit-ng/src/TextAreaMimeData.cpp:23
#10 0x00002ad03d827676 in QMimeDataPrivate::retrieveTypedData(QString const&, QVariant::Type) const () at /lib64/libQt5Core.so.5
#11 0x00002ad03d82888d in QMimeData::data(QString const&) const () at /lib64/libQt5Core.so.5
#12 0x00002ad03d20c0f6 in QInternalMimeData::renderDataHelper(QString const&, QMimeData const*) () at /lib64/libQt5Gui.so.5
#13 0x00002ad045bb25ff in QXcbMime::mimeDataForAtom(QXcbConnection*, unsigned int, QMimeData*, QByteArray*, unsigned int*, int*) () at /lib64/libQt5XcbQpa.so.5
#14 0x00002ad045ba2a35 in QXcbClipboard::sendSelection(QMimeData*, unsigned int, unsigned int, unsigned int) () at /lib64/libQt5XcbQpa.so.5
#15 0x00002ad045ba31c5 in QXcbClipboard::handleSelectionRequest(xcb_selection_request_event_t*) () at /lib64/libQt5XcbQpa.so.5
#16 0x00002ad045baa31e in QXcbConnection::handleXcbEvent(xcb_generic_event_t*) () at /lib64/libQt5XcbQpa.so.5
#17 0x00002ad045bac19e in QXcbConnection::processXcbEvents() () at /lib64/libQt5XcbQpa.so.5
#18 0x00002ad03d82e1de in QObject::event(QEvent*) () at /lib64/libQt5Core.so.5
#19 0x00002ad03cbebd8c in QApplicationPrivate::notify_helper(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#20 0x00002ad03cbf2f68 in QApplication::notify(QObject*, QEvent*) () at /lib64/libQt5Widgets.so.5
#21 0x00002ad03d804be6 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /lib64/libQt5Core.so.5
#22 0x00002ad03d807503 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () at /lib64/libQt5Core.so.5
#23 0x00002ad03d853ab3 in postEventSourceDispatch(_GSource*, int (*)(void*), void*) () at /lib64/libQt5Core.so.5
#24 0x00002ad04210a099 in g_main_context_dispatch () at /lib64/libglib-2.0.so.0
#25 0x00002ad04210a3f8 in g_main_context_iterate.isra.19 () at /lib64/libglib-2.0.so.0
#26 0x00002ad04210a4ac in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#27 0x00002ad03d85345c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib64/libQt5Core.so.5
#28 0x00002ad03d8036db in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /lib64/libQt5Core.so.5
#29 0x00002ad03d80bc04 in QCoreApplication::exec() () at /lib64/libQt5Core.so.5
#30 0x0000000000488a15 in main(int, char**) (argc=<optimized out>, argv=<optimized out>) at /tmp/nedit-ng/src/nedit.cpp:126
eteran commented 4 years ago

OK, seems that my attempt at a simple fix wasn't enough. I have other ideas on how to approach it though.

eteran commented 4 years ago

PS. I've been editing your tickets, but if you can remember, please wrap things like the above in markdown code blocks. It makes them easier to read and prevents GitHub from thinking that things like #123 are referencing another issue in the repo.

marilmanen commented 4 years ago

This is now in use, I'll let you know if I can make it crash

eteran commented 4 years ago

@marilmanen 2 days and no crash reported? Could this have been the fix for good?!

eteran commented 4 years ago

Over a week with no reported crashes. Being optimistic and closing this bug!

Please re-open if the problem persists.

marilmanen commented 4 years ago

I was traveling (Kyushu Basho), so not much tested, but seems to be ok ....