NSATSTypeSetter exception

  • I'm seeing the following exception occasionally in my console log, and I suspect it may be due to a quicklook plugin that I'm at least partly responsible for.  It uses NSLayoutManager to draw an attributed string.  The string drawing code is appended as well, since presumably that's relevant.  The attributed string has a mix of fonts and NSTextAttachmentCells, if that matters.  Any suggestions would be appreciated.

    thanks,
    adam

    01/18/08 09:21:36 quicklookd[128] <NSATSTypesetter: 0x149580>: Exception *** Collection <NSCFSet: 0x1d6f30> was mutated while being enumerated. raised during typesetting layout manager <NSLayoutManager: 0x1b8150>
        1 containers, text backing has 2656 characters
        selected character range {1082253312, 0} affinity: upstream granularity: character
        marked character range {1082253312, 0}
        Currently holding 2656 glyphs.
        Glyph tree contents:  2656 characters, 2656 glyphs, 1 nodes, 32 node bytes, 4096 storage bytes, 4128 total bytes, 1.55 bytes per character, 1.55 bytes per glyph
        Layout tree contents:  2656 characters, 2656 glyphs, 0 laid glyphs, 0 laid line fragments, 1 nodes, 32 node bytes, 0 storage bytes, 32 total bytes, 0.01 bytes per character, 0.01 bytes per glyph, 0.00 laid glyphs per laid line fragment, 0.00 bytes per laid line fragment
    , glyph range {0 21}. Ignoring...

    // creates a new NSTextStorage/NSLayoutManager/NSTextContainer system suitable for drawing in a thread
    static NSTextStorage *createTextStorage()
    {
        NSTextStorage *textStorage = [[NSTextStorage alloc] init];
        NSLayoutManager *lm = [[NSLayoutManager alloc] init];
        NSTextContainer *tc = [[NSTextContainer alloc] init];
        [tc setContainerSize:_containerSize];
        [lm addTextContainer:tc];
        // don't let the layout manager use its threaded layout (see header)
        [lm setBackgroundLayoutEnabled:NO];
        [textStorage addLayoutManager:lm];
        // retained by layout manager
        [tc release];
        // retained by text storage
        [lm release];
        // see header; the CircleView example sets it to NO
        [lm setUsesScreenFonts:YES];

        return textStorage;
    }

    // assumes that the current NSGraphicsContext is the destination
    static void drawAttributedStringInCurrentContext(NSAttributedString *attrString)
    {
        CGContextRef ctxt = [[NSGraphicsContext currentContext] graphicsPort];

        NSTextStorage *textStorage = createTextStorage();
        [textStorage beginEditing];
        [textStorage setAttributedString:attrString];

        [textStorage endEditing];
        NSRect stringRect = NSZeroRect;
        stringRect.size = _paperSize;

        CGContextSaveGState(ctxt);

        CGAffineTransform t1 = CGAffineTransformMakeTranslation(_horizontalMargin, _paperSize.height - _verticalMargin);
        CGAffineTransform t2 = CGAffineTransformMakeScale(1, -1);
        CGAffineTransform pageTransform = CGAffineTransformConcat(t2, t1);
        CGContextConcatCTM(ctxt, pageTransform);

        // objectAtIndex:0 is safe, since we added these to the text storage (so there's at least one)
        NSLayoutManager *lm = [[textStorage layoutManagers] objectAtIndex:0];
        NSTextContainer *tc = [[lm textContainers] objectAtIndex:0];

        NSRange glyphRange;

        // we now have a properly flipped graphics context, so force layout and then draw the text
        glyphRange = [lm glyphRangeForBoundingRect:stringRect inTextContainer:tc];
        NSRect usedRect = [lm usedRectForTextContainer:tc];

        // NSRunStorage raises if we try drawing a zero length range (happens if you have an empty text file)
        if (glyphRange.length > 0) {
            [lm drawBackgroundForGlyphRange:glyphRange atPoint:usedRect.origin];
            [lm drawGlyphsForGlyphRange:glyphRange atPoint:usedRect.origin];
        }
        CGContextRestoreGState(ctxt);
        [textStorage release];
    }
  • The log is essentially saying that a NSMutableSet detected mutation
    while being enumerated.
    Since there are many call out points from the layout process (and The
    Text System doesn't enumerate any NSSet), it's hard to say what's
    causing the exception.

    One thing you could do is to try removing your  quicklook plug-in for
    a while and see if the log still gets generated.
    If so, please file a bug.

    Thanks,

    Aki

    On 2008/01/18, at 9:53, Adam R. Maxwell wrote:

    > I'm seeing the following exception occasionally in my console log,
    > and I suspect it may be due to a quicklook plugin that I'm at least
    > partly responsible for.  It uses NSLayoutManager to draw an
    > attributed string.  The string drawing code is appended as well,
    > since presumably that's relevant.  The attributed string has a mix
    > of fonts and NSTextAttachmentCells, if that matters.  Any
    > suggestions would be appreciated.
    >
    > thanks,
    > adam
    >
    > 01/18/08 09:21:36 quicklookd[128] <NSATSTypesetter: 0x149580>:
    > Exception *** Collection <NSCFSet: 0x1d6f30> was mutated while being
    > enumerated. raised during typesetting layout manager
    > <NSLayoutManager: 0x1b8150>
    > 1 containers, text backing has 2656 characters
    > selected character range {1082253312, 0} affinity: upstream
    > granularity: character
    > marked character range {1082253312, 0}
    > Currently holding 2656 glyphs.
    > Glyph tree contents:  2656 characters, 2656 glyphs, 1 nodes, 32
    > node bytes, 4096 storage bytes, 4128 total bytes, 1.55 bytes per
    > character, 1.55 bytes per glyph
    > Layout tree contents:  2656 characters, 2656 glyphs, 0 laid
    > glyphs, 0 laid line fragments, 1 nodes, 32 node bytes, 0 storage
    > bytes, 32 total bytes, 0.01 bytes per character, 0.01 bytes per
    > glyph, 0.00 laid glyphs per laid line fragment, 0.00 bytes per laid
    > line fragment
    > , glyph range {0 21}. Ignoring...
    >
    >
    > // creates a new NSTextStorage/NSLayoutManager/NSTextContainer
    > system suitable for drawing in a thread
    > static NSTextStorage *createTextStorage()
    > {
    > NSTextStorage *textStorage = [[NSTextStorage alloc] init];
    > NSLayoutManager *lm = [[NSLayoutManager alloc] init];
    > NSTextContainer *tc = [[NSTextContainer alloc] init];
    > [tc setContainerSize:_containerSize];
    > [lm addTextContainer:tc];
    > // don't let the layout manager use its threaded layout (see
    > header)
    > [lm setBackgroundLayoutEnabled:NO];
    > [textStorage addLayoutManager:lm];
    > // retained by layout manager
    > [tc release];
    > // retained by text storage
    > [lm release];
    > // see header; the CircleView example sets it to NO
    > [lm setUsesScreenFonts:YES];
    >
    > return textStorage;
    > }
    >
    > // assumes that the current NSGraphicsContext is the destination
    > static void drawAttributedStringInCurrentContext(NSAttributedString
    > *attrString)
    > {
    > CGContextRef ctxt = [[NSGraphicsContext currentContext]
    > graphicsPort];
    >
    > NSTextStorage *textStorage = createTextStorage();
    > [textStorage beginEditing];
    > [textStorage setAttributedString:attrString];
    >
    > [textStorage endEditing];
    > NSRect stringRect = NSZeroRect;
    > stringRect.size = _paperSize;
    >
    > CGContextSaveGState(ctxt);
    >
    > CGAffineTransform t1 =
    > CGAffineTransformMakeTranslation(_horizontalMargin,
    > _paperSize.height - _verticalMargin);
    > CGAffineTransform t2 = CGAffineTransformMakeScale(1, -1);
    > CGAffineTransform pageTransform = CGAffineTransformConcat(t2, t1);
    > CGContextConcatCTM(ctxt, pageTransform);
    >
    > // objectAtIndex:0 is safe, since we added these to the text
    > storage (so there's at least one)
    > NSLayoutManager *lm = [[textStorage layoutManagers] objectAtIndex:
    > 0];
    > NSTextContainer *tc = [[lm textContainers] objectAtIndex:0];
    >
    > NSRange glyphRange;
    >
    > // we now have a properly flipped graphics context, so force
    > layout and then draw the text
    > glyphRange = [lm glyphRangeForBoundingRect:stringRect
    > inTextContainer:tc];
    > NSRect usedRect = [lm usedRectForTextContainer:tc];
    >
    > // NSRunStorage raises if we try drawing a zero length range
    > (happens if you have an empty text file)
    > if (glyphRange.length > 0) {
    > [lm drawBackgroundForGlyphRange:glyphRange
    > atPoint:usedRect.origin];
    > [lm drawGlyphsForGlyphRange:glyphRange
    > atPoint:usedRect.origin];
    > }
    > CGContextRestoreGState(ctxt);
    > [textStorage release];
    > }
  • Hi Aki,

    I filed this a couple of weeks ago as rdar://problem/5670606.  I now suspect this particular plugin because the thumbnail drawing failed while it was drawing the text (at least, the icon is only partially drawn).  Unfortunately, the exception only appears once every few weeks at most, so it's pretty hard to prove whether it still occurs or not.

    thanks,
    Adam

    On Friday, January 18, 2008, at 11:13AM, "Aki Inoue" <aki...> wrote:
    > The log is essentially saying that a NSMutableSet detected mutation
    > while being enumerated.
    > Since there are many call out points from the layout process (and The
    > Text System doesn't enumerate any NSSet), it's hard to say what's
    > causing the exception.
    >
    > One thing you could do is to try removing your  quicklook plug-in for
    > a while and see if the log still gets generated.
    > If so, please file a bug.
    >
    > Thanks,
    >
    > Aki
    >
    > On 2008/01/18, at 9:53, Adam R. Maxwell wrote:
    >
    >> I'm seeing the following exception occasionally in my console log,
    >> and I suspect it may be due to a quicklook plugin that I'm at least
    >> partly responsible for.  It uses NSLayoutManager to draw an
    >> attributed string.  The string drawing code is appended as well,
    >> since presumably that's relevant.  The attributed string has a mix
    >> of fonts and NSTextAttachmentCells, if that matters.  Any
    >> suggestions would be appreciated.
    >>
    >> thanks,
    >> adam
    >>
    >> 01/18/08 09:21:36 quicklookd[128] <NSATSTypesetter: 0x149580>:
    >> Exception *** Collection <NSCFSet: 0x1d6f30> was mutated while being
    >> enumerated. raised during typesetting layout manager
    >> <NSLayoutManager: 0x1b8150>
    >> 1 containers, text backing has 2656 characters
    >> selected character range {1082253312, 0} affinity: upstream
    >> granularity: character
    >> marked character range {1082253312, 0}
    >> Currently holding 2656 glyphs.
    >> Glyph tree contents:  2656 characters, 2656 glyphs, 1 nodes, 32
    >> node bytes, 4096 storage bytes, 4128 total bytes, 1.55 bytes per
    >> character, 1.55 bytes per glyph
    >> Layout tree contents:  2656 characters, 2656 glyphs, 0 laid
    >> glyphs, 0 laid line fragments, 1 nodes, 32 node bytes, 0 storage
    >> bytes, 32 total bytes, 0.01 bytes per character, 0.01 bytes per
    >> glyph, 0.00 laid glyphs per laid line fragment, 0.00 bytes per laid
    >> line fragment
    >> , glyph range {0 21}. Ignoring...
    >>
    >>
    >> // creates a new NSTextStorage/NSLayoutManager/NSTextContainer
    >> system suitable for drawing in a thread
    >> static NSTextStorage *createTextStorage()
    >> {
    >> NSTextStorage *textStorage = [[NSTextStorage alloc] init];
    >> NSLayoutManager *lm = [[NSLayoutManager alloc] init];
    >> NSTextContainer *tc = [[NSTextContainer alloc] init];
    >> [tc setContainerSize:_containerSize];
    >> [lm addTextContainer:tc];
    >> // don't let the layout manager use its threaded layout (see
    >> header)
    >> [lm setBackgroundLayoutEnabled:NO];
    >> [textStorage addLayoutManager:lm];
    >> // retained by layout manager
    >> [tc release];
    >> // retained by text storage
    >> [lm release];
    >> // see header; the CircleView example sets it to NO
    >> [lm setUsesScreenFonts:YES];
    >>
    >> return textStorage;
    >> }
    >>
    >> // assumes that the current NSGraphicsContext is the destination
    >> static void drawAttributedStringInCurrentContext(NSAttributedString
    >> *attrString)
    >> {
    >> CGContextRef ctxt = [[NSGraphicsContext currentContext]
    >> graphicsPort];
    >>
    >> NSTextStorage *textStorage = createTextStorage();
    >> [textStorage beginEditing];
    >> [textStorage setAttributedString:attrString];
    >>
    >> [textStorage endEditing];
    >> NSRect stringRect = NSZeroRect;
    >> stringRect.size = _paperSize;
    >>
    >> CGContextSaveGState(ctxt);
    >>
    >> CGAffineTransform t1 =
    >> CGAffineTransformMakeTranslation(_horizontalMargin,
    >> _paperSize.height - _verticalMargin);
    >> CGAffineTransform t2 = CGAffineTransformMakeScale(1, -1);
    >> CGAffineTransform pageTransform = CGAffineTransformConcat(t2, t1);
    >> CGContextConcatCTM(ctxt, pageTransform);
    >>
    >> // objectAtIndex:0 is safe, since we added these to the text
    >> storage (so there's at least one)
    >> NSLayoutManager *lm = [[textStorage layoutManagers] objectAtIndex:
    >> 0];
    >> NSTextContainer *tc = [[lm textContainers] objectAtIndex:0];
    >>
    >> NSRange glyphRange;
    >>
    >> // we now have a properly flipped graphics context, so force
    >> layout and then draw the text
    >> glyphRange = [lm glyphRangeForBoundingRect:stringRect
    >> inTextContainer:tc];
    >> NSRect usedRect = [lm usedRectForTextContainer:tc];
    >>
    >> // NSRunStorage raises if we try drawing a zero length range
    >> (happens if you have an empty text file)
    >> if (glyphRange.length > 0) {
    >> [lm drawBackgroundForGlyphRange:glyphRange
    >> atPoint:usedRect.origin];
    >> [lm drawGlyphsForGlyphRange:glyphRange
    >> atPoint:usedRect.origin];
    >> }
    >> CGContextRestoreGState(ctxt);
    >> [textStorage release];
    >> }
    >
    >
    >
previous month january 2008 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today