Memory leak in NSOperationQueue

Originator:tim.murison
Number:rdar://7128141 Date Originated:08/07/2009
Status:Open Resolved:
Product:Mac OS X Product Version:10.5.7 and 10.6A421
Classification:Serious Reproducible:Always
 
Summary:
========

Using NSOperationQueue results in a memory leak.

Steps to Reproduce:
===================

The following code reproduces the problem. The flow is as follows:
1) Queue up a batch of 1000 trivial NSOperations
2) Wait for the queue to empty
3) Sleep for a second to ensure there is no CPU load
4) Force a collection4
5) Rinse and repeat

Compile the following code with:
gcc -x objective-c main.m -o test -fobjc-gc-only -framework Cocoa -g

#import <Cocoa/Cocoa.h>
#include <libkern/OSAtomic.h>

volatile int64_t globalCounter;

@interface Operation : NSOperation
+ (Operation*) operation;
@end

@implementation Operation
+ (Operation*) operation
{
        return [[[Operation alloc] init] autorelease];
}

- (void) main
{
        OSAtomicIncrement64(&globalCounter);
}
@end

int main(int argc, char **argv)
{
        NSOperationQueue *queue = [[NSOperationQueue alloc] init];
        int64_t counter = 0;

        [queue setMaxConcurrentOperationCount:4];

        while (1) {
                [queue addOperation:[Operation operation]];
                counter++;

                if (counter % 1000 == 0) {
                        while ([[queue operations] count]) {
                                usleep(100);
                        }

                        usleep(1000 * 1000);
                        [[NSGarbageCollector defaultCollector] collectExhaustively];
                }
        }
}

Expected Results:
=================

No memory leak

Actual Results:
===============

Memory leak... a pretty quick one too!

Notes:
======
Please note, I have tried this on 10.5.7 and Snow Leopard 10A421, both platforms reproduce the problem. It is not reproducible with retain/release code.

Comments

This bug should be closed

You're not starting the collector thread.

Might be seeing something similar on iPhone OS 3.0.x

FWIW, I'm seeing similar/consistent behavior on iPhone OS 3.0 when using retain/release on my NSOperation objects. I was going to try autorelease, but then I saw this! :)

The leak seems to occur sometime after adding the operation to the queue. The queue length is set to the recommended value of NSOperationQueueDefaultMaxConcurrentOperationCount). It's a small leak (3.5 KB), but a leak nonetheless.


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!