Commits

Jens Alfke committed 5cab303

10.6 compatibility: Fix some new compiler warnings, and work around apparent regressions in NSTask and -stringByStandardizingPath.

Comments (0)

Files changed (4)

MYDirectoryWatcher.m

     self = [super init];
     if (self != nil) {
         _path = path.copy;
-        _standardizedPath = [[_path stringByStandardizingPath] copy];
+        // stringByStandardizingPath is supposed to resolve symlinks, but in 10.6 this seems to have stopped happening...
+        _standardizedPath = [[[path stringByResolvingSymlinksInPath] stringByStandardizingPath] copy];
         _target = target;
         _action = action;
         _latency = 5.0;
 - (NSString*) relativePath
 {
     NSString *base = watcher.standardizedPath;
-    NSString *standardizedPath = [path stringByStandardizingPath];
+    // stringByStandardizingPath is supposed to resolve symlinks, but in 10.6 this seems to have stopped happening...
+    NSString *standardizedPath = [[path stringByResolvingSymlinksInPath] stringByStandardizingPath];
     if( ! [standardizedPath hasPrefix: base] )
         return nil;
     unsigned length = base.length;
 
 //FIX: NOTICE: This code was written assuming garbage collection. It will currently leak like a sieve without it.
 
-
 NSString* const MYTaskErrorDomain = @"MYTaskError";
 NSString* const MYTaskExitCodeKey = @"MYTaskExitCode";
 NSString* const MYTaskObjectKey = @"MYTask";
         [self _close];
         return [self makeError: @"Exception launching %@: %@",_task.launchPath,x];
     }
+    LogTo(MYTaskVerbose, @"Launched task, modes %@", _modes);
+    Assert(_task.isRunning);
     _taskRunning = YES;
     self.isRunning = YES;
     
 
 - (void) stop
 {
+    LogTo(MYTaskVerbose, @"Stopping task");
     [_task interrupt];
     [self _close];
     _taskRunning = NO;
     if( n.object == _outHandle ) {
         if( data.length > 0 ) {
             [_outHandle readInBackgroundAndNotifyForModes: _modes];
-            LogTo(HgTaskVerbose, @"Got %u bytes of output",data.length);
+            LogTo(MYTaskVerbose, @"Got %u bytes of output",data.length);
             if( _outputData ) {
                 [self willChangeValueForKey: @"output"];
                 [self willChangeValueForKey: @"outputData"];
                 [self didChangeValueForKey: @"output"];
             }
         } else {
-            LogTo(HgTaskVerbose, @"Closed output");
+            LogTo(MYTaskVerbose, @"Closed output");
             _outHandle = nil;
             if( [self _shouldFinishUp] )
                 [self _finishUp];
         NSData *data = [n.userInfo objectForKey: NSFileHandleNotificationDataItem];
         if( data.length > 0 ) {
             [_errHandle readInBackgroundAndNotifyForModes: _modes];
-            LogTo(HgTaskVerbose, @"Got %u bytes of stderr",data.length);
+            LogTo(MYTaskVerbose, @"Got %u bytes of stderr",data.length);
             [self willChangeValueForKey: @"errorData"];
             [_errorData appendData: data];
             [self didChangeValueForKey: @"errorData"];
         } else {
-            LogTo(HgTaskVerbose, @"Closed stderr");
+            LogTo(MYTaskVerbose, @"Closed stderr");
             _errHandle = nil;
             if( [self _shouldFinishUp] )
                 [self _finishUp];
 - (void) _exited: (NSNotification*)n
 {
     _resultCode = _task.terminationStatus;
-    LogTo(HgTaskVerbose, @"Exited with result=%i",_resultCode);
+    LogTo(MYTaskVerbose, @"Exited with result=%i",_resultCode);
     _taskRunning = NO;
     if( [self _shouldFinishUp] )
         [self _finishUp];
     [NSObject cancelPreviousPerformRequestsWithTarget: self selector: @selector(_finishUp) object: nil];
     [self _close];
 
-    LogTo(HgTaskVerbose, @"Finished!");
+    LogTo(MYTaskVerbose, @"Finished!");
 
     if( _resultCode != 0 ) {
         // Handle errors:
 {
     // wait for task to exit:
     while( _task.isRunning || self.isRunning )
-        [[NSRunLoop currentRunLoop] runMode: MYTaskSynchronousRunLoopMode
-                                 beforeDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
+        if (![[NSRunLoop currentRunLoop] runMode: runLoopMode
+                                      beforeDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]]) {
+            // This happens if both stderr and stdout are closed (leaving no NSFileHandles running
+            // in this runloop mode) but the task hasn't yet notified me that it exited.
+            // For some reason, in 10.6 the notification sometimes just doesn't appear, so poll
+            // for it:
+            if (_task.isRunning) {
+                Warn(@"MYTask _waitTillFinishedInMode: no runloop sources left for %@ mode; waiting...", runLoopMode);
+                sleep(1);
+            } else {
+                Warn(@"MYTask _waitTillFinishedInMode: Task exited without notifying!");
+                [self _exited: nil];
+            }
+        } else
+            LogTo(MYTaskVerbose, @"..._waitTillFinishedInMode still waiting...");
+
     return (_resultCode==0);
 }
 
 
 struct TestCaseLink {void (*testptr)(); const char *name; BOOL passed; struct TestCaseLink *next;};
 extern struct TestCaseLink *gAllTestCases;
-#endif DEBUG
+#endif // DEBUG
 void _AssertFailed( id rcvr, const void *selOrFn, const char *sourceFile, int sourceLine,
                    const char *condString, NSString *message, ... ) __attribute__((noreturn));
 void _AssertAbstractMethodFailed( id rcvr, SEL cmd) __attribute__((noreturn));
 }
 
 
-#endif DEBUG
+#endif // DEBUG
 
 
 #pragma mark -