mirror of
https://github.com/transmission/transmission
synced 2025-01-03 05:25:52 +00:00
refactor: support deallocating VDKQueue object (#6290)
This commit is contained in:
parent
f85c3b6f8d
commit
e10689beea
2 changed files with 32 additions and 28 deletions
|
@ -136,10 +136,12 @@ extern NSString const* VDKQueueAccessRevocationNotification;
|
||||||
// Just add it or remove it and this class will take action only if appropriate.
|
// Just add it or remove it and this class will take action only if appropriate.
|
||||||
// (Add only if we're not already watching it, remove only if we are.)
|
// (Add only if we're not already watching it, remove only if we are.)
|
||||||
//
|
//
|
||||||
// Warning: You must pass full, root-relative paths. Do not pass tilde-abbreviated paths or file URLs.
|
// Warning: Only pass file paths ("/path"), not string representations of URLs ("file://path").
|
||||||
- (void)addPath:(NSString*)aPath;
|
- (void)addPath:(NSString*)aPath;
|
||||||
- (void)addPath:(NSString*)aPath notifyingAbout:(u_int)flags; // See note above for values to pass in "flags"
|
- (void)addPath:(NSString*)aPath notifyingAbout:(u_int)flags; // See note above for values to pass in "flags"
|
||||||
|
|
||||||
|
// Either `removePath:` or `removeAllPaths` must be called if we want this object to ever be dealloc'd.
|
||||||
|
// This is because adding a path detaches a thread which retains self.
|
||||||
- (void)removePath:(NSString*)aPath;
|
- (void)removePath:(NSString*)aPath;
|
||||||
- (void)removeAllPaths;
|
- (void)removeAllPaths;
|
||||||
|
|
||||||
|
|
|
@ -111,13 +111,11 @@ NSString const* VDKQueueAccessRevocationNotification = @"VDKQueueAccessWasRevoke
|
||||||
|
|
||||||
- (void)dealloc
|
- (void)dealloc
|
||||||
{
|
{
|
||||||
// Shut down the thread that's scanning for kQueue events
|
// Close our kqueue's file descriptor
|
||||||
_keepWatcherThreadRunning = NO;
|
if (close(_coreQueueFD) == -1)
|
||||||
|
{
|
||||||
// Do this to close all the open file descriptors for files we're watching
|
NSLog(@"VDKQueue watcherThread: Couldn't close main kqueue (%d)", errno);
|
||||||
[self removeAllPaths];
|
}
|
||||||
|
|
||||||
_watchedPathEntries = nil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
|
@ -171,22 +169,23 @@ NSString const* VDKQueueAccessRevocationNotification = @"VDKQueueAccessWasRevoke
|
||||||
|
|
||||||
- (void)watcherThread:(id)sender
|
- (void)watcherThread:(id)sender
|
||||||
{
|
{
|
||||||
int n;
|
|
||||||
struct kevent ev;
|
|
||||||
// 1 second timeout. Should be longer, but we need this thread to exit when a kqueue is dealloced, so 1 second timeout is quite a while to wait.
|
|
||||||
struct timespec timeout = { 1, 0 };
|
|
||||||
// So we don't have to risk accessing iVars when the thread is terminated.
|
|
||||||
int theFD = _coreQueueFD;
|
|
||||||
|
|
||||||
NSMutableArray* notesToPost = [[NSMutableArray alloc] initWithCapacity:5];
|
|
||||||
|
|
||||||
#if DEBUG_LOG_THREAD_LIFETIME
|
#if DEBUG_LOG_THREAD_LIFETIME
|
||||||
NSLog(@"watcherThread started.");
|
NSLog(@"watcherThread started.");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NSThread.currentThread.name = @"VDKQueue";
|
||||||
|
|
||||||
|
struct kevent ev;
|
||||||
|
// 1 second timeout. Should be longer, but we need this thread to exit when a kqueue is dealloced, so 1 second timeout is quite a while to wait.
|
||||||
|
const struct timespec timeout = { 1, 0 };
|
||||||
|
// So we don't have to risk accessing iVars when the thread is terminated.
|
||||||
|
int const theFD = _coreQueueFD;
|
||||||
|
|
||||||
|
NSMutableArray* notesToPost = [[NSMutableArray alloc] initWithCapacity:5];
|
||||||
|
|
||||||
while (_keepWatcherThreadRunning)
|
while (_keepWatcherThreadRunning)
|
||||||
{
|
{
|
||||||
n = kevent(theFD, NULL, 0, &ev, 1, &timeout);
|
int n = kevent(theFD, NULL, 0, &ev, 1, &timeout);
|
||||||
if (n <= 0 || ev.filter != EVFILT_VNODE || !ev.fflags)
|
if (n <= 0 || ev.filter != EVFILT_VNODE || !ev.fflags)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -254,12 +253,6 @@ NSString const* VDKQueueAccessRevocationNotification = @"VDKQueueAccessWasRevoke
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close our kqueue's file descriptor
|
|
||||||
if (close(theFD) == -1)
|
|
||||||
{
|
|
||||||
NSLog(@"VDKQueue watcherThread: Couldn't close main kqueue (%d)", errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG_LOG_THREAD_LIFETIME
|
#if DEBUG_LOG_THREAD_LIFETIME
|
||||||
NSLog(@"watcherThread finished.");
|
NSLog(@"watcherThread finished.");
|
||||||
#endif
|
#endif
|
||||||
|
@ -280,6 +273,8 @@ NSString const* VDKQueueAccessRevocationNotification = @"VDKQueueAccessWasRevoke
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aPath = aPath.stringByStandardizingPath;
|
||||||
|
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
if (_watchedPathEntries[aPath])
|
if (_watchedPathEntries[aPath])
|
||||||
|
@ -306,14 +301,17 @@ NSString const* VDKQueueAccessRevocationNotification = @"VDKQueueAccessWasRevoke
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
aPath = aPath.stringByStandardizingPath;
|
||||||
|
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
VDKQueuePathEntry* entry = _watchedPathEntries[aPath];
|
// Close the open file descriptor if we're watching it.
|
||||||
|
[_watchedPathEntries removeObjectForKey:aPath];
|
||||||
|
|
||||||
// Remove it only if we're watching it.
|
if (_watchedPathEntries.count == 0)
|
||||||
if (entry)
|
|
||||||
{
|
{
|
||||||
[_watchedPathEntries removeObjectForKey:aPath];
|
// Shut down the thread that's scanning for kQueue events.
|
||||||
|
_keepWatcherThreadRunning = NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,7 +320,11 @@ NSString const* VDKQueueAccessRevocationNotification = @"VDKQueueAccessWasRevoke
|
||||||
{
|
{
|
||||||
@synchronized(self)
|
@synchronized(self)
|
||||||
{
|
{
|
||||||
|
// Close all the open file descriptors for files we're watching.
|
||||||
[_watchedPathEntries removeAllObjects];
|
[_watchedPathEntries removeAllObjects];
|
||||||
|
|
||||||
|
// Shut down the thread that's scanning for kQueue events.
|
||||||
|
_keepWatcherThreadRunning = NO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue