Need -[NSTask waitUntilExitOrTimeout:] (was NSTask "Thread Unsafe"...)
Need -[NSTask waitUntilExitOrTimeout:] (was NSTask "Thread Unsafe"...)
- Subject: Need -[NSTask waitUntilExitOrTimeout:] (was NSTask "Thread Unsafe"...)
- From: Jerry Krinock <email@hidden>
- Date: Mon, 14 Sep 2009 18:29:02 -0700
The reason why I asked this is because I need:
-[NSTask waitUntilExitOrTimeout:(NSTimeInterval)].
But there is no such method. So, I wrote a wrapper around NSTask that
does this.
On 2009 Sep 14, at 07:41, Adam R. Maxwell wrote:
Ordinarily, I'd guess that it's supposed to mean that you can't
share instances between threads. However, guesswork when dealing
with the threading docs drives me crazy.
For NSTask in particular, I recommend that you interpret that more
conservatively...
Also, I presume it means that you should not invoke the same instance
from more than one thread. I'm not sure how much more conservative
you could get, other than to run it on the main thread.
I wrote an implementation of NSTask from scratch to work around the
problem.
Whew, Adam. Since I'm 10.5+, and don't think I'll ever be running
more than one NSTask at a time, I won't be quite that conservative.
In my NSTask wrapper, I detach a new thread. In this new thread, I
set up the task, then run the run loop once...
[task launch] ;
if ([task isRunning]) {
// Write data to stdin file/pipe
// ...
// ...
}
NSDate* limitTime = [NSDate dateWithTimeIntervalSinceNow:timeout] ;
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:limitTime] ;
// The above will block and be run to here either due to
// the posting of an NSTaskDidTerminateNotification, or the
// passing of limitTime, whichever occurs first.
if (![task isRunning]) {
taskResult = [task terminationStatus] ;
// Read stdout and stderr
// ...
// ...
}
else {
taskResult = SSYShellTaskerErrorTimedOut ;
// Clean up
kill([task processIdentifier], SIGKILL) ;
// Set NSError indicating timeout
// ...
// ...
}
Actually, I originally was doing this on the main thread, except that
the -[NSRunLoop runMode:beforeDate] was in a while() loop. When the
loop ran, I would check and see if there was a timeout, task was
finished, or neither (presumably some other input source triggered the
run). But then I found an obscure bug: If I had disabled undo
registration in order to do some behind-the-scenes changes, it would
re-enable undo registration. Uh, yeah, it took me a while to track
that one down. Apparently, running a run loop that is already running
is not a good idea. I suppose I could also have done it with a timer.
So, unless someone sees something wrong with detaching a new thread
for the sole purpose of running an NSTask, I'm good to go. This
version passes all of my unit tests ;)
_______________________________________________
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