when I use NSTask to execute cmd in a loop, sometime the NSTask will hang, code is like this
- (BOOL)waitUntilExitWithTimeout:(CFTimeInterval)TO sendTerm:(BOOL)SENDTERM sendKill:(BOOL)SENDKILL
{
CFAbsoluteTime started;
CFAbsoluteTime passed;
BOOL exited = NO;
if (![self isRunning])
return YES;
int pro_pid = [self processIdentifier];
started = CFAbsoluteTimeGetCurrent();
for (
CFAbsoluteTime now = started;
!exited && ((passed = now - started) < TO);
now = CFAbsoluteTimeGetCurrent()
)
{
if (![self isRunning])
{
exited = YES;
} else {
CFAbsoluteTime sleepTime = 0.1;
useconds_t sleepUsec = round(sleepTime * 1000000.0);
if (sleepUsec == 0) sleepUsec = 1;
usleep(sleepUsec); // sleep for 0.1 sec
}
}
if (!exited)
{
//NSLog(@"%@ didn't exit after timeout of %0.2f sec", self, TO);
if (SENDTERM)
{
TO = 2; // 2 second timeout, waiting for SIGTERM to kill process
//NSLog(@"%@ sending SIGTERM", self);
//[self terminate];
// UNIX way
pid_t pid = [self processIdentifier];
kill(pid, SIGTERM);
started = CFAbsoluteTimeGetCurrent();
for (
CFAbsoluteTime now = started;
!exited && ((passed = now - started) < TO);
now = CFAbsoluteTimeGetCurrent()
)
{
if (![self isRunning])
{
exited = YES;
} else {
usleep(100000);
}
}
}
if (!exited && SENDKILL)
{
TO = 2; // 2 second timeout, waiting for SIGKILL to kill process
//NSLog(@"%@ sending SIGKILL", self);
pid_t pid = [self processIdentifier];
kill(pid, SIGKILL);
started = CFAbsoluteTimeGetCurrent();
for (
CFAbsoluteTime now = started;
!exited && ((passed = now - started) < TO);
now = CFAbsoluteTimeGetCurrent()
)
{
if (![self isRunning])
{
exited = YES;
} else {
usleep(100000); // sleep for 0.1 sec
}
}
}
}
return exited;
}
- (void) Exec(const char * cmdWithArgs)
{
NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/sh"];
NSArray *arguments = [NSArray arrayWithObjects:
@"-c" ,
[NSString stringWithFormat:@"%s", cmdWithArgs],
nil];
[task setArguments: arguments];
NSPipe *pipe = [NSPipe pipe];
[task setStandardOutput: pipe];
[task launch];
NSFileHandle *file = [pipe fileHandleForReading];
NSData *data = [file readDataToEndOfFile];
[task waitUntilExitWithTimeout:30.0f sendTerm:YES sendKill:YES];
//sometime waitUntilExit will hang, sohttps://stackoverflow.com/questions/33423993/hanging-nstask-using-waituntilexit
//[task waitUntilExit];
[file closeFile];
}
std::string cmd = R"(netstat -rn | awk '/default/ {if ( index($6, "en0") > 0 ){print $2} }')";
while(1){
Exec(cmd.c_str());
}
when the test is hang, use lldb attached process, a deadlock occur. it seems caused by the lock in NSConcreteTask
anybody can help me ?