bugGNUstep - Bugs: bug #43454, Problem with Continuous Spell...


bug #43454: Problem with Continuous Spell Checking

Submitter:  Germán Arias <espectador>
Submitted:  Tue 21 Oct 2014 06:25:17 PM UTC
Category:  Gui/AppKit Severity:  3 - Normal
Item Group:  Bug Status:  None
Privacy:  Public Assigned to:  FredKiefer
Open/Closed:  Open
* Mandatory Fields

Add a New Comment Rich Markup

Jump to the original submission

Sun 16 Nov 2014 05:12:36 PM UTC, comment #11: 

I finally managed to reproduce the descriped behaviour with a slight variation of my code:

  [text insertText: @"Hola program"];
  NSLog(@"inserting text");
  [text setSelectedRange: NSMakeRange(5, 7)];
  [textStorage beginEditing];
  [text replaceCharactersInRange: NSMakeRange(5, 7) withString: @"programa"];
  [lm glyphAtIndex: 13 isValidIndex: &valid];
  [lm _generateRunsToCharacter: 13];
  [textStorage endEditing];
  [text didChangeText];
  NSLog(@"inserted text");

With this I get an ifinit loop and the glyph dump just looks like yours:

--- dumping runs
0x22014d0 13 chars, 13 glyphs, 1 complete, prev 0x206dea0 next 0x222a268
         level 0, continued 0
    0 0048 u0048      1 006f u006f      2 006c u006c      3 0061 u0061      4 0020 u0020      5 0070 u0070      6 0072 u0072      7 006f u006f      8 0067 u0067      9 0072 u0072     10 0061 u0061     11 006d u006d     12 0061 u0061 
0x222a268 1 chars, 0 glyphs, 0 complete, prev 0x22014d0 next    (nil)
         level 1, continued 0
- structure
    head: 0x22014d0 1   0   0|0x222a250 1  13  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|   (nil) 0  14  13|
0x22014d0: 0x222a268 1  13  13|
0x222a268:    (nil) 0   1   0|   (nil) 0   1   0|
--- done

With the commented out line,
[lm glyphAtIndex: 13 isValidIndex: &valid];
I get no glyph dumps and the following message:

Problem posting notification: <NSException: 0x20c2640> NAME:NSGenericException REASON:Glyph generation was triggered for a layout manager while the text storage it was attached to had unprocessed editing. This is not allowed. Glyph generation may be triggered only at points where calls to -beginEditing and -endEditing are balanced. INFO:(null)

Now with this in place I should be finally able to track down what is going wrong.

Fred Kiefer <FredKiefer>
Group Member
Wed 12 Nov 2014 05:29:55 AM UTC, comment #10: 

The problem should be in _textCheckingTimerFired: or _checkTextInRange:, which are called after the text has been edited. If I add:

[self setContinuousSpellCheckingEnabled: NO];

In _acceptGuess: before [_textStorage beginEditing]. The word is inserted without problem.

Germán Arias <espectador>
Tue 11 Nov 2014 10:58:29 PM UTC, comment #9: 

I am a bit confused that a break point at line 756 could still result in a loop. As there is no loop inside of _generateGlyphsUpToCharacter: this would mean that the loop is in _generateGlyphs_char_r:
Which again would mean that you only get the glyph dump before the change not after. But in your picuture I see that "Hole program" has been replaced by "Hola programa".
What is also strange is that the glyph skip list internaly referes to the index 14, although there should always have been 13 characters at most.

I tried to reproduce the behaviour with this bit of code:

  NSTextView *text = [[NSTextView alloc] initWithFrame: NSMakeRect(0,0,200,200)];

  [text insertText: @"Hola program"];
  NSLog(@"generateGlyphsUpToGlyph 0");
  NSLayoutManager *lm = [text layoutManager];
  NSTextStorage *textStorage = [text textStorage];
  NSLog(@"inserting text");
  [textStorage beginEditing];
  [text replaceCharactersInRange: NSMakeRange(5, 7) withString: @"programa"];
  [textStorage endEditing];
  [text didChangeText];
  NSLog(@"inserted text");

which should match what happens inside of _acceptGuess:, but this seems to work and never gives invalid glyph indexes.
I also tried to add calls to
[lm glyphAtIndex: 13 isValidIndex: &valid];
with different indexes, but none of that resulted in a loop.

Fred Kiefer <FredKiefer>
Group Member
Tue 11 Nov 2014 01:58:46 AM UTC, comment #8: 

Letting execute one time the line 756 goes into infinite loop. So is hard catch the output. But I send you this screenshot (attached) when the gdb hangs.

Germán Arias <espectador>
Sun 09 Nov 2014 10:53:47 PM UTC, comment #7: 

I now seem to have an idea what might cause the problem. With the selection not properly adjusted the text view tries to highlight behind the end of the text. This results in a glyoh past the end of the text being requested and this somehow leads to an infinit loop.

This will require two fixes. One for the calling method (_acceptGuess:), which is fairly simple. But we also need to fix the low level glyph code. It should never go into a loop, even when wrong numbers are given. What should happen is that "complete" gets set to 1 on the top level glyph run. But this doesn't happen and to understand why I need some more information.

In GSLayoutManager.m you see the commented out lines 732 and 734. Could you please activate them and run your example again? It will result in loads of output. What I am interested in is the first output after your last breakpoint. I think it is best to set another breakpoint on line 756 and have it execute exactly once.

Sorry to make it so complicated. I will add the simple fix after we understand what is going on here.

Fred Kiefer <FredKiefer>
Group Member
Thu 06 Nov 2014 07:26:18 AM UTC, comment #6: 

Here the backtrace I get with (using Ink):

break NSTextView.m:5822

when stop:

break GSLayoutManager.m:755

Tha backtrace:

#0  -[GSLayoutManager(GlyphsHelpers) _generateGlyphsUpToGlyph:] ()
    at GSLayoutManager.m:745
#1  0x003a0960 in -[GSLayoutManager(glyphs) glyphAtIndex:isValidIndex:] ()
    at GSLayoutManager.m:861
#2  0x003a7724 in -[GSHorizontalTypesetter _cacheGlyphs:] ()
    at GSHorizontalTypesetter.m:218
#3  0x003a8c1b in -[GSHorizontalTypesetter layoutLineNewParagraph:] ()
    at GSHorizontalTypesetter.m:562
#4  0x003a91ae in -[GSHorizontalTypesetter layoutGlyphsInLayoutManager:inTextContainer:startingAtGlyphIndex:previousLineFragmentRect:nextGlyphIndex:numberOfLineFragments:] () at GSHorizontalTypesetter.m:1281
#5  0x003a3354 in -[GSLayoutManager(LayoutHelpers) _doLayoutToContainer:] ()
    at GSLayoutManager.m:2000
#6  0x003a0b70 in -[GSLayoutManager(LayoutHelpers) _doLayout] ()
    at GSLayoutManager.m:1888
#7  0x00296ddf in -[NSLayoutManager(layout) _insertionPointRectForCharacterIndex:textContainer:] () at NSLayoutManager.m:871
#8  0x002953da in -[NSLayoutManager(layout) insertionPointRectForCharacterIndex:inTextContainer:] () at NSLayoutManager.m:975
#9  0x00000001 in ?? ()
#10 0x0033fa09 in -[NSTextView(leftovers) updateInsertionPointStateAndRestartTimer:] () at NSTextView.m:4224

As you can see, there isn't too much information. Aside that this hangs GDB and I need restart GNUstep services.

Germán Arias <espectador>
Fri 31 Oct 2014 02:16:27 PM UTC, comment #5: 

I submitted a patch for the specific issue of the last stack trace. This wont fix the whole issue reported here, but should reduce the visible symptoms.

It would be great if you could send me a stack trace of the other issue as well. Of course reduced to a managable size.

Fred Kiefer <FredKiefer>
Group Member
Sun 26 Oct 2014 10:39:44 PM UTC, comment #4: 

I think this two problems are related.

Backtrace when app crash:

Open Ink, select at menu Check Spelling Automatically and then write, notice the last space, "Hello programme " (without quotes). Then in contextual menu select "programmer". The app crash. Here the backtrace:

Program received signal SIGSEGV, Segmentation fault.
-[NSLayoutManager(drawing) drawBackgroundForGlyphRange:atPoint:] ()
    at NSLayoutManager.m:1413
1413          NSRange r = NSMakeRange(glyph_pos + i, glyph_run->head.glyph_length - i);
(gdb) backtrace
#0  -[NSLayoutManager(drawing) drawBackgroundForGlyphRange:atPoint:] ()
    at NSLayoutManager.m:1413
#1  0x0033b934 in -[NSTextView(leftovers) drawRect:] () at NSTextView.m:4003
#2  0x00360eda in -[NSView displayRectIgnoringOpacity:inContext:] ()
    at NSView.m:2570
#3  0x00355e3b in -[NSView displayRectIgnoringOpacity:] () at NSView.m:2519
#4  0x00360acf in -[NSView displayIfNeededInRectIgnoringOpacity:] ()
    at NSView.m:2450
#5  0x00360d01 in -[NSView displayIfNeededInRectIgnoringOpacity:] ()
    at NSView.m:2476
#6  0x00360d01 in -[NSView displayIfNeededInRectIgnoringOpacity:] ()
    at NSView.m:2476
#7  0x00360d01 in -[NSView displayIfNeededInRectIgnoringOpacity:] ()
    at NSView.m:2476
#8  0x00360d01 in -[NSView displayIfNeededInRectIgnoringOpacity:] ()
    at NSView.m:2476
#9  0x00355d06 in -[NSView displayIfNeededInRect:] () at NSView.m:2428
#10 0x00355b77 in -[NSView displayIfNeeded] () at NSView.m:2410
#11 0x00367b2f in -[NSWindow displayIfNeeded] () at NSWindow.m:2431
#12 0x00366478 in -[NSWindow(GNUstepPrivate) _handleAutodisplay] ()
    at NSWindow.m:189
#13 0x003716ab in +[NSWindow(GNUstepPrivate) _handleAutodisplay:] ()
    at NSWindow.m:218
#14 0x0080a5ba in -[NSObject performSelector:withObject:] () at NSObject.m:2046
---Type <return> to continue, or q <return> to quit--
#15 0x0083f989 in -[GSRunLoopPerformer fire] () at NSRunLoop.m:110
#16 0x00842631 in -[NSRunLoop(Private) _checkPerformers:] () at NSRunLoop.m:493
#17 0x008413a5 in -[NSRunLoop runMode:beforeDate:] () at NSRunLoop.m:1265
#18 0x00383885 in -[GSDisplayServer(EventOps) getEventMatchingMask:beforeDate:inMode:dequeue:] () at GSDisplayServer.m:1040
#19 0x0291c4b7 in -[XGServer(X11Ops) getEventMatchingMask:beforeDate:inMode:dequeue:] () at XGServerEvent.m:2571
#20 0x00202bf7 in -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] () at ../Headers/Additions/GNUstepGUI/GSDisplayServer.h:207
#21 0x0020109d in -[NSApplication run] () at NSApplication.m:1553
#22 0x001e3aeb in NSApplicationMain () at Functions.m:91
#23 0x08048e57 in main () at main.m:33

The other problem:

Open Ink, select at menu Check Spelling Automatically and then write "Hello programme" this time without space at the end (without quotes). Then in contextual menu select "programmer", the app hangs. This doesn't occurs if you write only one word, for example "programm". Only if you write two or more words. The odd thing here, is that auto complete also use -replaceCharactersInRange:withString: and works OK. For example, open Gemas, create a new Objective-C document, select at menu "Check Spelling Automatically", and then write something like "#import NSMutabl" (without quotes) and press Control-p to open the auto complete list, now select something like NSMutableDictionary and this is inserted without problem.

Germán Arias <espectador>
Sun 26 Oct 2014 04:23:25 PM UTC, comment #3: 

Could you please provide a stack trace of the issue?

You seem to be describing two different situations. In one case you talk about a crash and in the other about an indefinitely running loop. What are the different ways to trigger these behaviours?

I looked over the code in NSTextView and in GSLayoutManager and the only obvious problem I could see is that the insertion of a spelling correction via insertText: wont change the selected range. And this also doesn't call beginEditing/endEditing, but as far as I remember this shouldn't be needed for just one single change.

It really would help to see whether the problem occures directly from _acceptGuess: or changeSpelling: or happens later on.

Fred Kiefer <FredKiefer>
Group Member
Sun 26 Oct 2014 06:36:25 AM UTC, comment #2: 

More info.

If you add one space after the last word (the wrong word). And then try to spell the word with the contextual menu, the app crash with the message:

run_for_glyph_index failed for 0

Germán Arias <espectador>
Thu 23 Oct 2014 05:27:41 PM UTC, comment #1: 

The problem is the while loop in _generateGlyphsUpToGlyph: (NSLayoutManager), which run indefinitely. However I need further investigation to find why this happen.

Germán Arias <espectador>
Tue 21 Oct 2014 06:25:17 PM UTC, original submission:  

The problem occurs when the last word in the container is wrong and the user selects a guess word, in the contextual menu, with a length greater that the selected word at textview. In this case the app hangs. To reproduce:

1) Open Ink.
2) Write some words and put the last word wrong.
3) Open contextual menu and select a word with a length greater than the selected word in textview.
4) The app hangs.

Maybe this is a problem with replaceCharactersInRange:withString:. But I don't found documentation about how this method works.

Germán Arias <espectador>


(Note: upload size limit is set to 16384 kB, after insertion of the required escape characters.)

Attach Files:

Attached Files
file #32410:  bug.jpg added by espectador (117KiB - image/jpeg - Screenshot of the bug.)


Depends on the following items: None found

Items that depend on this one: None found


Carbon-Copy List
  • -email is unavailable- added by FredKiefer (Posted a comment)
  • -email is unavailable- added by espectador (Submitted the item)

    There are 0 votes so far. Votes easily highlight which items people would like to see resolved in priority, independently of the priority of the item set by tracker managers.

    Only logged-in users can vote.


    Follow 2 latest changes.

    Date Changed by Updated Field Previous Value => Replaced by
    2014-11-11 espectador Attached File- Added bug.jpg, #32410
    2014-10-26 FredKiefer Assigned toNone FredKiefer

    Back to the top

    Powered by Savane 3.13-1277.
    Corresponding source code