0
我的可可應用程序有多線程(最多8個線程)運行一個使用NSTask約需1200秒的Python腳本。幾乎在運行NSTask的8個線程的每個執行過程中,該應用程序幾乎永遠等待並永不返回。我暫停了執行,發現應用程序停留在waitUntilExit中。 我的代碼片段如下。請幫助讓我知道我可以如何解決這個問題。NSTask信號量在多重卡住waitUntilExit
dispatch_semaphore_t MySemaphore;
...
MySemaphore = dispatch_semaphore_create(8);
...
//Code portion where NSTask is used to execute a python script.
...
NSTask* task = [NSTask new];
[task setLaunchPath:launchPath];
[task setArguments:[NSArray arrayWithObjects:param1,
param2, param3,
param4, param5,
param6, param7, nil]];
NSData *outData;
NSData *errorData;
int retVal;
dispatch_semaphore_wait(MySemaphore, DISPATCH_TIME_FOREVER);
retVal = [self _runTask:task
inData:nil
outData:&outData
errorData:&errorData];
dispatch_semaphore_signal(MySemaphore);
NSMutableString *retStr = [[[NSMutableString alloc] initWithData:outData
encoding:NSUTF8StringEncoding] autorelease];
NSMutableString *retStrErr = [[[NSMutableString alloc] initWithData:errorData
encoding:NSUTF8StringEncoding] autorelease];
if([retStrErr length] != 0)
{
[retStr appendString:@"\nstandard Error output:\n"];
[retStr appendString:retStrErr];
}
if(retVal == 0)
{
[retStr appendString:@"\nOK\n"];
}
else
{
[retStr appendString:@"\nERROR\n"];
}
NSLog(@"Response of _DRAMRetention for UUT:%d, %@", nUut+1, retStr);
[task release];
...
- (int) _runTask:(NSTask*)task inData:(NSData*)inData outData:(NSData**)outData errorData:(NSData**)errorData
{
NSPipe* inPipe = nil;
NSPipe* outPipe = nil;
NSPipe* errorPipe = nil;
NSFileHandle* fileHandle;
/* Reset output variables */
if(outData)
{
*outData = nil;
}
if(errorData)
{
*errorData = nil;
}
/* Safe check */
if(task == nil)
{
return -1;
}
/* Create standard input pipe */
if([inData length])
{
if((inPipe = [NSPipe new]))
{
[task setStandardInput:inPipe];
[inPipe release];
}
else
{
task = nil;
goto Exit;
}
}
/* Create standard output pipe */
if(outData)
{
if((outPipe = [NSPipe new]))
{
[task setStandardOutput:outPipe];
[outPipe release];
}
else
{
task = nil;
goto Exit;
}
}
/* Create standard error pipe */
if(errorData)
{
if((errorPipe = [NSPipe new]))
{
[task setStandardError:errorPipe];
[errorPipe release];
}
else
{
task = nil;
goto Exit;
}
}
/* Launch task */
NS_DURING
[task launch];
NS_HANDLER
task = nil;
NS_ENDHANDLER
if(task == nil)
{
goto Exit;
}
/* Write data to standard input pipe */
if((fileHandle = [inPipe fileHandleForWriting]))
{
NS_DURING
[fileHandle writeData:inData];
[fileHandle closeFile];
NS_HANDLER
[task terminate];
[task interrupt];
task = nil;
NS_ENDHANDLER
}
if(task == nil)
{
goto Exit;
}
/* Wait for task to complete and read data from standard output and standard error pipes in background */
if((fileHandle = [outPipe fileHandleForReading]))
{
*outData = [NSMutableData data];
[[NSNotificationCenter defaultCenter] addObserver:*outData selector:@selector(_CommandLineToolFileHandleDataAvailable:) name:NSFileHandleDataAvailableNotification object:fileHandle];
[fileHandle waitForDataInBackgroundAndNotify];
}
if((fileHandle = [errorPipe fileHandleForReading]))
{
*errorData = [NSMutableData data];
[[NSNotificationCenter defaultCenter] addObserver:*errorData selector:@selector(_CommandLineToolFileHandleDataAvailable:) name:NSFileHandleDataAvailableNotification object:fileHandle];
[fileHandle waitForDataInBackgroundAndNotify];
}
//My app is stuck here
[task waitUntilExit];
if((fileHandle = [errorPipe fileHandleForReading]))
{
[[NSNotificationCenter defaultCenter] removeObserver:*errorData name:NSFileHandleDataAvailableNotification object:fileHandle];
[(NSMutableData*)*errorData appendData:[fileHandle readDataToEndOfFile]];
}
if((fileHandle = [outPipe fileHandleForReading]))
{
[[NSNotificationCenter defaultCenter] removeObserver:*outData name:NSFileHandleDataAvailableNotification object:fileHandle];
[(NSMutableData*)*outData appendData:[fileHandle readDataToEndOfFile]];
}
Exit:
[[inPipe fileHandleForReading] closeFile];
[[inPipe fileHandleForWriting] closeFile];
[[outPipe fileHandleForReading] closeFile];
[[outPipe fileHandleForWriting] closeFile];
[[errorPipe fileHandleForReading] closeFile];
[[errorPipe fileHandleForWriting] closeFile];
return (task ? [task terminationStatus] : -1);
}
@end
@implementation NSMutableData (CommandLineTool)
/* Extend the NSMutableData class to add a method called by NSFileHandleDataAvailableNotification to automatically append the new data */
- (void) _CommandLineToolFileHandleDataAvailable:(NSNotification*)notification
{
NSFileHandle* fileHandle = [notification object];
[self appendData:[fileHandle availableData]];
[fileHandle waitForDataInBackgroundAndNotify];
}
是的我確定Python腳本正在終止。你還建議我做什麼來解決這個問題,在nstask waituntilexit問題上「永遠等待」? – user2370312
@ user2370312除了確保從輸出管道讀取所有數據之外,我不確定。我試圖想想還有什麼會阻止終止,併成爲空白。 – bbum