Re: NSTask in separate thread is leaking memory
Re: NSTask in separate thread is leaking memory
- Subject: Re: NSTask in separate thread is leaking memory
- From: Ken Thomases <email@hidden>
- Date: Wed, 4 Feb 2009 05:30:29 -0600
On Feb 4, 2009, at 4:49 AM, Oleg Krupnov wrote:
I use an NSTask to collect system info from system_profiler. Because
it takes a while to complete, I launch that task in a separate thread,
to avoid UI from freezing.
Both NSTask and NSFileHandle provide asynchronous interfaces, so it is
not necessary to use a separate thread.
- (void)systemProfilerThread:(id)ignored
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *configuration = nil;
NSPipe* inputPipe = [NSPipe pipe];
You do nothing with inputPipe, so you should just get rid of it. If
you want the task to not inherit your standard input, do [scriptTask
setStandardInput:[NSFileHandle fileHandleWithNullDevice]].
NSPipe* outputPipe = [NSPipe pipe];
NSTask* scriptTask = [[[NSTask alloc] init] autorelease];
[scriptTask setLaunchPath:@"/usr/sbin/system_profiler"];
[scriptTask setArguments:[NSArray arrayWithObjects:@"-detailLevel",
@"mini", nil]];
[scriptTask setStandardOutput:outputPipe];
[scriptTask launch];
[[inputPipe fileHandleForWriting] closeFile];
configuration = [[[NSString alloc] initWithData:[[outputPipe
fileHandleForReading] readDataToEndOfFile]
encoding:NSUTF8StringEncoding] autorelease];
if (!m_isCanceled)
{
[m_target performSelectorOnMainThread:m_action
withObject:configuration waitUntilDone:NO];
}
[pool drain];
}
The problem is, according to the Leaks tool, is that there's a memory
leak in -systemProfilerThread. The leak disappears if I launch the
task in the main thread.
You don't say what is leaking or where it was allocated from.
I've read in docs that NSTask is NOT thread safe, but does it also
apply to the above case, when the NSTask object is created and
released within a single thread, though not the main thread? If NSTask
cannot be used this way, then which way I should use it?
Create and launch the task from the main thread. Register for the
task termination notification, if you're interested.
Also register for notification of read-to-end-of-file completion on
the output file handle, and invoke -
readToEndOfFileInBackgroundAndNotify on it. In the handler for that
notification is where you can decode/parse the data.
After you have registered for these notifications and launched the
task, return immediately. Don't block waiting for either the task to
terminate or data to arrive from the file handle.
Also, what puzzles me is why, first and foremost, the main thread is
blocked until the task is complete? I do not call wait -waitUntilExit.
I would expect that the main thread is not blocked, but I receive the
NSTaskDidTerminateNotification, but it does not happens with the code
above.
I assume you mean the main thread is blocked if you _don't_ detach a
separate thread, right? In that case, it's because you're using -
readDataToEndOfFile, which is synchronous. It doesn't return until it
has read to the end of the output from system_profiler -- that is,
when system_profiler terminates and closes its standard output.
Also, where are you registering for NSTaskDidTerminateNotification? I
don't see it above. In any case, regardless of on which thread you
register for that notification, I would expect it to be posted on the
thread which created the NSTask. Although notifications are not
normally passed through the run loop, this particular notification is
the result of the framework "noticiing" that the task has completed
(an event which is, of course, external to your program and the
framework's direct knowledge). In order to notice that, the framework
needs the run loop of the thread to run. You never run the run loop
for your thread in the code above.
I suspect, in fact, that that's the cause of the memory leak. The
framework had some housekeeping to do that relies on the run loop
running.
Cheers,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden