1
0
mirror of https://github.com/ksherlock/TwoTerm.git synced 2025-01-09 15:32:56 +00:00

Thread to monitor child.

git-svn-id: svn://qnap.local/TwoTerm/trunk@1998 5590a31f-7b70-45f8-8c82-aa3a8e5f4507
This commit is contained in:
Kelvin Sherlock 2011-01-17 16:32:39 +00:00
parent c253bec21c
commit 91878398b4
2 changed files with 142 additions and 0 deletions

44
ChildMonitor.h Normal file

@ -0,0 +1,44 @@
//
// ChildMonitor.h
// 2Term
//
// Created by Kelvin Sherlock on 1/16/2011.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
/*
* An NSThread to monitor a pid and fd.
* requires 10.5+
*
*/
#import <Foundation/Foundation.h>
@class ChildMonitor;
@protocol ChildMonitorDelegate
-(void)childDataAvailable: (ChildMonitor *)monitor;
-(void)childFinished: (ChildMonitor *)monitor;
@end
@interface ChildMonitor : NSThread {
pid_t _childPID;
int _fd;
int _childStatus;
BOOL _childFinished;
id<ChildMonitorDelegate> _delegate;
}
@property (assign) BOOL childFinished;
@property (assign) int childStatus;
@property (nonatomic, assign) pid_t childPID;
@property (nonatomic, assign) int fd;
@property (nonatomic, assign) id<ChildMonitorDelegate> delegate;
@end

98
ChildMonitor.m Normal file

@ -0,0 +1,98 @@
//
// ChildMonitor.m
// 2Term
//
// Created by Kelvin Sherlock on 1/16/2011.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "ChildMonitor.h"
#include <sys/wait.h>
#include <sys/select.h>
#include <signal.h>
@implementation ChildMonitor
@synthesize childFinished = _childFinished;
@synthesize childStatus = _childStatus;
@synthesize childPID = _childPID;
@synthesize fd = _fd;
@synthesize delegate = _delegate;
-(BOOL)wait
{
int status = 0;
if (waitpid(_childPID, &status, WNOHANG) == _childPID)
{
[self setChildStatus: status];
[self setChildFinished: YES];
[(NSObject *)_delegate performSelectorOnMainThread: @selector(childFinished:)
withObject: self
waitUntilDone: NO];
return YES;
}
return NO;
}
-(void)main
{
int fd = _fd;
for(;;)
{
int n;
struct timeval tm;
fd_set read_set;
fd_set error_set;
if ([self isCancelled]) break;
FD_ZERO(&read_set);
FD_SET(fd, &read_set);
FD_ZERO(&error_set);
FD_SET(fd, &error_set);
// 10 second timeout...
tm.tv_sec = 10;
tm.tv_usec = 0;
n = select(fd + 1, &read_set, NULL, &error_set, &tm);
if (n == 0) continue;
if (n < 0) break;
if (FD_ISSET(fd, &error_set)) break;
// ?
if (FD_ISSET(fd, &read_set))
{
[_delegate childDataAvailable: self];
}
if ([self wait]) break;
}
if (!_childFinished) [self wait];
}
- (void)dealloc {
if (!_childFinished) kill(_childPID, 9);
[super dealloc];
}
@end