I'm getting lots of reports of crashes like this: Anyone have ideas? Code is below
@interface NTDispatchSource ()
@property (nonatomic, assign) id<NTDispatchSourceDelegateProtocol> delegate;
@property (nonatomic, retain) NTFileDesc *desc;
@property (nonatomic, assign) int fd;
@property (nonatomic, assign) dispatch_source_t dispatchSource;
@end
@interface NTDispatchSource(Private)
- (void)closeFile;
- (void)setupDispatchSource;
@end
void closeFDAsync(int theFD, NTFileDesc* theDesc);
@implementation NTDispatchSource
@synthesize fd, dispatchSource;
@synthesize delegate;
@synthesize desc;
+ (NTDispatchSource*)source:(NTFileDesc*)desc delegate:(id<NTDispatchSourceDelegateProtocol>)delegate;
{
NTDispatchSource* result = [[self alloc] init];
result.fd = -1; // initialize as invalid
[result setDelegate:delegate];
[result setDesc:desc];
[result setupDispatchSource];
return [result autorelease];
}
- (void)dealloc
{
if ([self delegate])
[NSException raise:@"must call clearDelegate" format:@"%@", NSStringFromClass([self class])];
[self setDesc:nil];
[self closeFile];
[super dealloc];
}
- (void)clearDelegate;
{
// I think I'm being retained by the eventhandler since it can message me
if (self.dispatchSource)
{
dispatch_source_cancel(self.dispatchSource);
dispatch_release(self.dispatchSource);
self.dispatchSource = 0;
}
[self setDelegate:nil];
}
@end
@implementation NTDispatchSource(Private)
- (void)setupDispatchSource;
{
// pipe files hang open (this stuff needs to be in a thread in any case, needs fix)
if (![[self desc] isPipe])
{
self.fd = open([[self desc] fileSystemPath], O_EVTONLY, 0);
if (self.fd != -1)
{
const NSUInteger sourceFlags = (DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE); // not including DISPATCH_VNODE_LINK
self.dispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,
self.fd,
sourceFlags,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
if (self.dispatchSource)
{
// Install the event handler to process the name change
dispatch_source_set_event_handler(self.dispatchSource, ^{
// execute on main thread
dispatch_async(dispatch_get_main_queue(), ^{
@try {
[[self delegate] sourceWasModified:self];
}
@catch (NSException * e) {
NSLog(@"setupDispatchSource exception: %@", e);
}
@finally {
}
});
});
// Install a cancellation handler to free the descriptor
// and the stored string.
dispatch_source_set_cancel_handler(self.dispatchSource, ^{
[self closeFile];
});
// Start processing events.
dispatch_resume(self.dispatchSource);
}
else
[self closeFile];
}
}
}
- (void)closeFile;
{
if (self.fd != -1)
{
// getting some main even loop hangs on close. Not sure why, so added this threaded close method
closeFDAsync(self.fd, [self desc]);
self.fd = -1;
}
}
- (NSString*)description;
{
return [NSString stringWithFormat:@"%@ : %@", NSStringFromClass([self class]), [[self desc] path]];
}
@end
void closeFDAsync(int theFD, NTFileDesc* theDesc)
{
if (theFD != -1)
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
@try {
int res = close(theFD);
if (res == -1)
NSLog(@"%@ close failed: %s\n%@", @"closeFDAsync()", strerror(errno), [theDesc path]);
}
@catch (NSException * e) {
NSLog(@"closeFDAsync exception: %@", e);
}
@finally {
}
});
}
}