-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Description
Description of the problem or steps to reproduce
Call main.Buffer.ReOpen on a large binary file (e.g. the micro binary) and observe it hang completely.
You can try this out yourself by installing the filemanager plugin, running the tree command and attempting to open the micro binary with TAB.
Specifications
You can use micro -version to get the commit hash.
Commit hash: de35d00
OS: Ubuntu 18.04.1 LTS
Terminal: GNOME Terminal
Other Information
I've narrowed this down to the String() method of main.LineArray:
Lines 118 to 128 in de35d00
| // Returns the String representation of the LineArray | |
| func (la *LineArray) String() string { | |
| str := "" | |
| for i, l := range la.lines { | |
| str += string(l.data) | |
| if i != len(la.lines)-1 { | |
| str += "\n" | |
| } | |
| } | |
| return str | |
| } |
This method is called by main.EventHandler.ApplyDiff() (L89)
micro/cmd/micro/eventhandler.go
Lines 83 to 101 in de35d00
| // ApplyDiff takes a string and runs the necessary insertion and deletion events to make | |
| // the buffer equal to that string | |
| // This means that we can transform the buffer into any string and still preserve undo/redo | |
| // through insert and delete events | |
| func (eh *EventHandler) ApplyDiff(new string) { | |
| differ := dmp.New() | |
| diff := differ.DiffMain(eh.buf.String(), new, false) | |
| loc := eh.buf.Start() | |
| for _, d := range diff { | |
| if d.Type == dmp.DiffDelete { | |
| eh.Remove(loc, loc.Move(Count(d.Text), eh.buf)) | |
| } else { | |
| if d.Type == dmp.DiffInsert { | |
| eh.Insert(loc, d.Text) | |
| } | |
| loc = loc.Move(Count(d.Text), eh.buf) | |
| } | |
| } | |
| } |
The issue is that eh.buf (in the case of the micro binary) is about 100k elements long, causing String() to pretty much crash the whole thing.
Attempted Fix
I tried changing this method to use the new strings.Builder but it did not seem to help.
Potential Solution
One potential solution I came up with is checking the equality of the old and new line arrays before diffing them, which is slow (takes maybe 1/4 a second) but doesn't hang micro completely.
This issues causes #1208 (filemanager calls ReOpen when opening a file for some reason).