NSAnimation crashing on Leopard;

  • Hello all,

    We found a strange crash in our app with NSAnimation. It appears to
    have something to do with the blocking mode of
    NSAnimationNonBlockingThreaded.

    The crash is very reproduceable, and you can do it simply with the
    attached sample code. Create a new app, put a textfield on the main
    window in IB, instantiate the AppController object in IB, and set it
    to be the window's delegate (and hook up the text field you created).

    If you then run the code and resize the window a bunch, it will crash
    on you. Usually takes about 10-20 seconds of resizing. However, if I
    change the NSAnimationNonblockingThreaded to NSAnimationNonblocking,
    it doesn't crash and works fine. Unfortunately, my app requires each
    animation to be in its own thread, so I need to use that mode.

    Any ideas what is happening here? When I try it on Tiger, it doesn't
    crash, but the weird thing always was that the number of threads
    (from Activity Monitor) goes through the roof...it's like they never
    die off when I stop and restart the animation. Does Leopard enforce a
    maximum number of threads or something?

      - Matt

    //--------------------------------------------------
    #import <Cocoa/Cocoa.h>

    @interface AppController : NSObject {
        IBOutlet NSTextField *lblValue; //Attach this to a NSTextView in IB
        NSAnimation *_oAnimator;
    }

    @end

    @implementation AppController

    - (id)init
    {
        if (self = [super init]) {
            _oAnimator = [[NSAnimation alloc] init];
            [_oAnimator setDelegate: self];
            [_oAnimator setAnimationBlockingMode:
    NSAnimationNonblockingThreaded];
            [_oAnimator setAnimationCurve: NSAnimationEaseInOut];
            [_oAnimator addProgressMark: 0.00];
            [_oAnimator addProgressMark: 0.25];
            [_oAnimator addProgressMark: 0.50];
            [_oAnimator addProgressMark: 0.75];
            [_oAnimator addProgressMark: 1.00];
        }
        return self;
    }

    - (void)dealloc
    {
        [_oAnimator setDelegate: nil];
        [_oAnimator release];

        [super dealloc];
    }

    - (void)windowDidResize: (NSNotification *)poNotification
    {
        [_oAnimator stopAnimation];
        [_oAnimator setDuration: 1.0];
        [_oAnimator startAnimation];
    }

    - (void)animation: (NSAnimation*)poAnimation didReachProgressMark:
    (NSAnimationProgress)pfProgress
    {
        if (poAnimation == _oAnimator) {
            [lblValue setStringValue: [NSString stringWithFormat: @"%f",
    pfProgress]];
        }
    }

    @end
    //--------------------------------------------------
  • No response here, so I've filed an Apple bug for this: 5610019.

      - Matt

    On 19-Nov-07, at 4:04 PM, Matt Budd wrote:

    > We found a strange crash in our app with NSAnimation. It appears to
    > have something to do with the blocking mode of
    > NSAnimationNonBlockingThreaded.
    >
    > The crash is very reproduceable, and you can do it simply with the
    > attached sample code. Create a new app, put a textfield on the main
    > window in IB, instantiate the AppController object in IB, and set
    > it to be the window's delegate (and hook up the text field you
    > created).
    >
    > If you then run the code and resize the window a bunch, it will
    > crash on you. Usually takes about 10-20 seconds of resizing.
    > However, if I change the NSAnimationNonblockingThreaded to
    > NSAnimationNonblocking, it doesn't crash and works fine.
    > Unfortunately, my app requires each animation to be in its own
    > thread, so I need to use that mode.
    >
    > Any ideas what is happening here? When I try it on Tiger, it
    > doesn't crash, but the weird thing always was that the number of
    > threads (from Activity Monitor) goes through the roof...it's like
    > they never die off when I stop and restart the animation. Does
    > Leopard enforce a maximum number of threads or something?
    >
    > - Matt
    >
    >
    > //--------------------------------------------------
    > #import <Cocoa/Cocoa.h>
    >
    > @interface AppController : NSObject {
    > IBOutlet NSTextField *lblValue; //Attach this to a NSTextView
    > in IB
    > NSAnimation *_oAnimator;
    > }
    >
    > @end
    >
    >
    > @implementation AppController
    >
    > - (id)init
    > {
    > if (self = [super init]) {
    > _oAnimator = [[NSAnimation alloc] init];
    > [_oAnimator setDelegate: self];
    > [_oAnimator setAnimationBlockingMode:
    > NSAnimationNonblockingThreaded];
    > [_oAnimator setAnimationCurve: NSAnimationEaseInOut];
    > [_oAnimator addProgressMark: 0.00];
    > [_oAnimator addProgressMark: 0.25];
    > [_oAnimator addProgressMark: 0.50];
    > [_oAnimator addProgressMark: 0.75];
    > [_oAnimator addProgressMark: 1.00];
    > }
    > return self;
    > }
    >
    > - (void)dealloc
    > {
    > [_oAnimator setDelegate: nil];
    > [_oAnimator release];
    >
    > [super dealloc];
    > }
    >
    > - (void)windowDidResize: (NSNotification *)poNotification
    > {
    > [_oAnimator stopAnimation];
    > [_oAnimator setDuration: 1.0];
    > [_oAnimator startAnimation];
    > }
    >
    > - (void)animation: (NSAnimation*)poAnimation didReachProgressMark:
    > (NSAnimationProgress)pfProgress
    > {
    > if (poAnimation == _oAnimator) {
    > [lblValue setStringValue: [NSString stringWithFormat: @"%
    > f", pfProgress]];
    > }
    > }
    >
    > @end
    > //--------------------------------------------------
  • Could this be crashing because you are updating the text field
    outside the main thread?

    There might be a special case for allowing UI updates from an
    NSAnimationNonblockingThreaded threads, in which case you have hit a
    bug, but I don't recall seeing any mention of this in the docs.

    If NSAnimationNonblockingThreaded isn't documented as permitting
    thread-safe UI updates, then the behaviour you're seeing is as
    documented - expect crashes.

    You'll either need to avoid using NSAnimationNonblockingThreaded -
    NSAnimationNonblocking should be ok for most purposes. If you can't
    avoid it, you'll need to perform UI updates via
    performSelectorOnMainThread, or similar.

    On 21 Nov 2007, at 16:42, Matt Budd wrote:

    > No response here, so I've filed an Apple bug for this: 5610019.
    >
    > - Matt
    >
    > On 19-Nov-07, at 4:04 PM, Matt Budd wrote:
    >
    >> We found a strange crash in our app with NSAnimation. It appears
    >> to have something to do with the blocking mode of
    >> NSAnimationNonBlockingThreaded.
    >>
    >> The crash is very reproduceable, and you can do it simply with the
    >> attached sample code. Create a new app, put a textfield on the
    >> main window in IB, instantiate the AppController object in IB, and
    >> set it to be the window's delegate (and hook up the text field you
    >> created).
    >>
    >> If you then run the code and resize the window a bunch, it will
    >> crash on you. Usually takes about 10-20 seconds of resizing.
    >> However, if I change the NSAnimationNonblockingThreaded to
    >> NSAnimationNonblocking, it doesn't crash and works fine.
    >> Unfortunately, my app requires each animation to be in its own
    >> thread, so I need to use that mode.
    >>
    >> Any ideas what is happening here? When I try it on Tiger, it
    >> doesn't crash, but the weird thing always was that the number of
    >> threads (from Activity Monitor) goes through the roof...it's like
    >> they never die off when I stop and restart the animation. Does
    >> Leopard enforce a maximum number of threads or something?
    >>
    >> - Matt
    >>
    >>
    >> //--------------------------------------------------
    >> #import <Cocoa/Cocoa.h>
    >>
    >> @interface AppController : NSObject {
    >> IBOutlet NSTextField *lblValue; //Attach this to a NSTextView
    >> in IB
    >> NSAnimation *_oAnimator;
    >> }
    >>
    >> @end
    >>
    >>
    >> @implementation AppController
    >>
    >> - (id)init
    >> {
    >> if (self = [super init]) {
    >> _oAnimator = [[NSAnimation alloc] init];
    >> [_oAnimator setDelegate: self];
    >> [_oAnimator setAnimationBlockingMode:
    >> NSAnimationNonblockingThreaded];
    >> [_oAnimator setAnimationCurve: NSAnimationEaseInOut];
    >> [_oAnimator addProgressMark: 0.00];
    >> [_oAnimator addProgressMark: 0.25];
    >> [_oAnimator addProgressMark: 0.50];
    >> [_oAnimator addProgressMark: 0.75];
    >> [_oAnimator addProgressMark: 1.00];
    >> }
    >> return self;
    >> }
    >>
    >> - (void)dealloc
    >> {
    >> [_oAnimator setDelegate: nil];
    >> [_oAnimator release];
    >>
    >> [super dealloc];
    >> }
    >>
    >> - (void)windowDidResize: (NSNotification *)poNotification
    >> {
    >> [_oAnimator stopAnimation];
    >> [_oAnimator setDuration: 1.0];
    >> [_oAnimator startAnimation];
    >> }
    >>
    >> - (void)animation: (NSAnimation*)poAnimation didReachProgressMark:
    >> (NSAnimationProgress)pfProgress
    >> {
    >> if (poAnimation == _oAnimator) {
    >> [lblValue setStringValue: [NSString stringWithFormat: @"%
    >> f", pfProgress]];
    >> }
    >> }
    >>
    >> @end
    >> //--------------------------------------------------

    >
  • Hey Martin,

    Thanks for the suggestion. I tried taking out the setStringValue and
    doing nothing (i.e. having no visual feedback), and it still crashes
    on Leopard. Still something specific to
    NSAnimationNonblockingThreaded. I have reworked my application to use
    NSAnimationNonblocking, but it really is a bug that Apple should fix
    on their end.

      - Matt

    On 25-Nov-07, at 5:47 AM, Martin Redington wrote:

    >
    > Could this be crashing because you are updating the text field
    > outside the main thread?
    >
    > There might be a special case for allowing UI updates from an
    > NSAnimationNonblockingThreaded threads, in which case you have hit
    > a bug, but I don't recall seeing any mention of this in the docs.
    >
    > If NSAnimationNonblockingThreaded isn't documented as permitting
    > thread-safe UI updates, then the behaviour you're seeing is as
    > documented - expect crashes.
    >
    > You'll either need to avoid using NSAnimationNonblockingThreaded -
    > NSAnimationNonblocking should be ok for most purposes. If you can't
    > avoid it, you'll need to perform UI updates via
    > performSelectorOnMainThread, or similar.
    >
    >
    >
    > On 21 Nov 2007, at 16:42, Matt Budd wrote:
    >
    >> No response here, so I've filed an Apple bug for this: 5610019.
    >>
    >> - Matt
    >>
    >> On 19-Nov-07, at 4:04 PM, Matt Budd wrote:
    >>
    >>> We found a strange crash in our app with NSAnimation. It appears
    >>> to have something to do with the blocking mode of
    >>> NSAnimationNonBlockingThreaded.
    >>>
    >>> The crash is very reproduceable, and you can do it simply with
    >>> the attached sample code. Create a new app, put a textfield on
    >>> the main window in IB, instantiate the AppController object in
    >>> IB, and set it to be the window's delegate (and hook up the text
    >>> field you created).
    >>>
    >>> If you then run the code and resize the window a bunch, it will
    >>> crash on you. Usually takes about 10-20 seconds of resizing.
    >>> However, if I change the NSAnimationNonblockingThreaded to
    >>> NSAnimationNonblocking, it doesn't crash and works fine.
    >>> Unfortunately, my app requires each animation to be in its own
    >>> thread, so I need to use that mode.
    >>>
    >>> Any ideas what is happening here? When I try it on Tiger, it
    >>> doesn't crash, but the weird thing always was that the number of
    >>> threads (from Activity Monitor) goes through the roof...it's like
    >>> they never die off when I stop and restart the animation. Does
    >>> Leopard enforce a maximum number of threads or something?
    >>>
    >>> - Matt
    >>>
    >>>
    >>> //--------------------------------------------------
    >>> #import <Cocoa/Cocoa.h>
    >>>
    >>> @interface AppController : NSObject {
    >>> IBOutlet NSTextField *lblValue; //Attach this to a NSTextView
    >>> in IB
    >>> NSAnimation *_oAnimator;
    >>> }
    >>>
    >>> @end
    >>>
    >>>
    >>> @implementation AppController
    >>>
    >>> - (id)init
    >>> {
    >>> if (self = [super init]) {
    >>> _oAnimator = [[NSAnimation alloc] init];
    >>> [_oAnimator setDelegate: self];
    >>> [_oAnimator setAnimationBlockingMode:
    >>> NSAnimationNonblockingThreaded];
    >>> [_oAnimator setAnimationCurve: NSAnimationEaseInOut];
    >>> [_oAnimator addProgressMark: 0.00];
    >>> [_oAnimator addProgressMark: 0.25];
    >>> [_oAnimator addProgressMark: 0.50];
    >>> [_oAnimator addProgressMark: 0.75];
    >>> [_oAnimator addProgressMark: 1.00];
    >>> }
    >>> return self;
    >>> }
    >>>
    >>> - (void)dealloc
    >>> {
    >>> [_oAnimator setDelegate: nil];
    >>> [_oAnimator release];
    >>>
    >>> [super dealloc];
    >>> }
    >>>
    >>> - (void)windowDidResize: (NSNotification *)poNotification
    >>> {
    >>> [_oAnimator stopAnimation];
    >>> [_oAnimator setDuration: 1.0];
    >>> [_oAnimator startAnimation];
    >>> }
    >>>
    >>> - (void)animation: (NSAnimation*)poAnimation
    >>> didReachProgressMark: (NSAnimationProgress)pfProgress
    >>> {
    >>> if (poAnimation == _oAnimator) {
    >>> [lblValue setStringValue: [NSString stringWithFormat: @"%
    >>> f", pfProgress]];
    >>> }
    >>> }
    >>>
    >>> @end
    >>> //--------------------------------------------------

    >>
    >
previous month november 2007 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    
Go to today