From 073fb54804c55f1ff06921b39ba37bf04c5e9844 Mon Sep 17 00:00:00 2001 From: Richard Frith-MacDonald Date: Sun, 9 Apr 2017 09:56:55 +0000 Subject: [PATCH] apply bug #49021 git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@40461 72102866-910b-0410-8b05-ffd578937521 --- ChangeLog | 7 +++++ Headers/Foundation/NSTask.h | 3 +++ Source/NSTask.m | 51 +++++++++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/ChangeLog b/ChangeLog index 98fbc4c68..610716fd2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2017-04-09 Richard Frith-Macdonald + + * Headers/Foundation/NSTask.h: + * Source/NSTask.m: + Apply OSX compatibility fix for NSTask notifications (bug #49021) + by Larry Campbell. + 2017-04-03 Richard Frith-Macdonald * Source/NSOperation.m: Fix leak spotted by David Lobron. diff --git a/Headers/Foundation/NSTask.h b/Headers/Foundation/NSTask.h index 88c4fb03c..1fab857e3 100644 --- a/Headers/Foundation/NSTask.h +++ b/Headers/Foundation/NSTask.h @@ -36,6 +36,8 @@ extern "C" { #endif +@class NSThread; + #if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST) enum { NSTaskTerminationReasonExit = 1, @@ -61,6 +63,7 @@ typedef NSInteger NSTaskTerminationReason; BOOL _hasTerminated; BOOL _hasCollected; BOOL _hasNotified; + NSThread *_launchingThread; NSTaskTerminationReason _terminationReason; #endif #if GS_NONFRAGILE diff --git a/Source/NSTask.m b/Source/NSTask.m index 0dd07c01a..ec10e40c3 100644 --- a/Source/NSTask.m +++ b/Source/NSTask.m @@ -222,6 +222,7 @@ pty_slave(const char* name) @interface NSTask (Private) - (NSString *) _fullLaunchPath; - (void) _collectChild; +- (void) _notifyOfTermination; - (void) _terminatedChild: (int)status reason: (NSTaskTerminationReason)reason; @end @@ -317,6 +318,7 @@ pty_slave(const char* name) RELEASE(_standardError); RELEASE(_standardInput); RELEASE(_standardOutput); + RELEASE(_launchingThread); [super dealloc]; } @@ -407,10 +409,16 @@ pty_slave(const char* name) * Raises an NSInvalidArgumentException if the launch path is not * set or if the subtask cannot be started for some reason * (eg. the executable does not exist or the task has already been launched). + * The actual launching is done in a concrete subclass; this method just + * takes care of actions common to all subclasses. */ - (void) launch { - [self subclassResponsibility: _cmd]; + if (_launchingThread != [NSThread currentThread]) + { + [_launchingThread release]; + _launchingThread = [[NSThread currentThread] retain]; + } } /** @@ -900,6 +908,22 @@ pty_slave(const char* name) [self subclassResponsibility: _cmd]; } +- (void) _notifyOfTermination +{ + NSNotificationQueue *q; + NSNotification *n; + + n = [NSNotification notificationWithName: NSTaskDidTerminateNotification + object: self + userInfo: nil]; + + q = [NSNotificationQueue defaultQueue]; + [q enqueueNotification: n + postingStyle: NSPostASAP + coalesceMask: NSNotificationNoCoalescing + forModes: nil]; +} + - (void) _terminatedChild: (int)status reason: (NSTaskTerminationReason)reason { [tasksLock lock]; @@ -912,17 +936,18 @@ pty_slave(const char* name) _hasTerminated = YES; if (_hasNotified == NO) { - NSNotification *n; - _hasNotified = YES; - n = [NSNotification notificationWithName: NSTaskDidTerminateNotification - object: self - userInfo: nil]; - - [[NSNotificationQueue defaultQueue] enqueueNotification: n - postingStyle: NSPostASAP - coalesceMask: NSNotificationNoCoalescing - forModes: nil]; + if (_launchingThread != nil) + { + [self performSelector: @selector(_notifyOfTermination) + onThread: _launchingThread + withObject: nil + waitUntilDone: NO]; + } + else + { + [self _notifyOfTermination]; + } } } @@ -1128,6 +1153,8 @@ quotedFromString(NSString *aString) format: @"NSTask - task has already been launched"]; } + [super launch]; + lpath = [self _fullLaunchPath]; wexecutable = (const unichar*)[lpath fileSystemRepresentation]; @@ -1455,6 +1482,8 @@ GSPrivateCheckTasks() format: @"NSTask - task has already been launched"]; } + [super launch]; + lpath = [self _fullLaunchPath]; executable = [lpath fileSystemRepresentation]; args[0] = executable;