Add newere method

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@39924 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-MacDonald 2016-06-26 05:56:10 +00:00
parent 35962654cb
commit 04406427e3
5 changed files with 122 additions and 53 deletions

View file

@ -1,3 +1,11 @@
2016-06-26 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSTask.h:
* Source/NSTask.m:
* Tests/base/NSTask/general.m:
* Tests/base/NSTask/notify.m:
Add -terminationReason method from OSX10.5
2016-06-25 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSMessagePort.m:

View file

@ -36,6 +36,14 @@
extern "C" {
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
enum {
NSTaskTerminationReasonExit = 1,
NSTaskTerminationReasonUncaughtSignal = 2
};
typedef NSInteger NSTaskTerminationReason;
#endif
@interface NSTask : NSObject
{
#if GS_EXPOSE(NSTask)
@ -53,6 +61,7 @@ extern "C" {
BOOL _hasTerminated;
BOOL _hasCollected;
BOOL _hasNotified;
NSTaskTerminationReason _terminationReason;
#endif
#if GS_NONFRAGILE
#else
@ -97,6 +106,9 @@ extern "C" {
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
- (int) processIdentifier;
#endif
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
- (NSTaskTerminationReason) terminationReason;
#endif
- (int) terminationStatus;
/*

View file

@ -118,6 +118,10 @@ static void handleSignal(int sig)
}
#ifdef _WIN32
/* We use exit code 10 to denote a process termination.
* Windows does nt have an exit code to denote termination this way.
*/
#define WIN_SIGNALLED 10
@interface NSConcreteWindowsTask : NSTask
{
@public
@ -222,7 +226,7 @@ pty_slave(const char* name)
@interface NSTask (Private)
- (NSString *) _fullLaunchPath;
- (void) _collectChild;
- (void) _terminatedChild: (int)status;
- (void) _terminatedChild: (int)status reason: (NSTaskTerminationReason)reason;
@end
@ -673,6 +677,30 @@ pty_slave(const char* name)
#endif
}
/**
* Returns the termination reason of the task.<br />
* If the task has not completed running, raises an
* NSInvalidArgumentException.
*/
- (NSTaskTerminationReason) terminationReason
{
if (_hasLaunched == NO)
{
[NSException raise: NSInvalidArgumentException
format: @"NSTask - task has not yet launched"];
}
if (_hasCollected == NO)
{
[self _collectChild];
}
if (_hasTerminated == NO)
{
[NSException raise: NSInvalidArgumentException
format: @"NSTask - task has not yet terminated"];
}
return _terminationReason;
}
/**
* Returns the termination status of the task.<br />
* If the task has not completed running, raises an
@ -876,13 +904,14 @@ pty_slave(const char* name)
[self subclassResponsibility: _cmd];
}
- (void) _terminatedChild: (int)status
- (void) _terminatedChild: (int)status reason: (NSTaskTerminationReason)reason
{
[tasksLock lock];
IF_NO_GC([[self retain] autorelease];)
NSMapRemove(activeTasks, (void*)(intptr_t)_taskId);
[tasksLock unlock];
_terminationStatus = status;
_terminationReason = reason;
_hasCollected = YES;
_hasTerminated = YES;
if (_hasNotified == NO)
@ -930,7 +959,9 @@ GSPrivateCheckTasks()
{
if (eCode != STILL_ACTIVE)
{
[t _terminatedChild: eCode];
[t _terminatedChild: eCode reason: (WIN_SIGNALLED == eCode)
? NSTaskTerminationReasonUncaughtSignal
: NSTaskTerminationReasonExit];
found = YES;
}
}
@ -972,8 +1003,11 @@ GSPrivateCheckTasks()
return;
}
/* We use exit code 10 to denote a process termination.
* Windows does nt have an exit code to denote termination this way.
*/
_hasTerminated = YES;
TerminateProcess(procInfo.hProcess, 10);
TerminateProcess(procInfo.hProcess, WIN_SIGNALLED);
}
@ -1307,7 +1341,9 @@ quotedFromString(NSString *aString)
}
else if (eCode != STILL_ACTIVE)
{
[self _terminatedChild: eCode];
[self _terminatedChild: eCode reason: (WIN_SIGNALLED == eCode)
? NSTaskTerminationReasonUncaughtSignal
: NSTaskTerminationReasonExit];
}
}
}
@ -1364,7 +1400,8 @@ GSPrivateCheckTasks()
NSLog(@"waitpid %d, exit status = %d",
result, status);
#endif
[t _terminatedChild: WEXITSTATUS(status)];
[t _terminatedChild: WEXITSTATUS(status)
reason: NSTaskTerminationReasonExit];
found = YES;
}
else if (WIFSIGNALED(status))
@ -1373,7 +1410,8 @@ GSPrivateCheckTasks()
NSLog(@"waitpid %d, termination status = %d",
result, status);
#endif
[t _terminatedChild: WTERMSIG(status)];
[t _terminatedChild: WTERMSIG(status)
reason: NSTaskTerminationReasonUncaughtSignal];
found = YES;
}
else
@ -1669,7 +1707,8 @@ GSPrivateCheckTasks()
NSLog(@"waitpid %d, exit status = %d",
result, status);
#endif
[self _terminatedChild: WEXITSTATUS(status)];
[self _terminatedChild: WEXITSTATUS(status)
reason: NSTaskTerminationReasonExit];
}
else if (WIFSIGNALED(status))
{
@ -1677,7 +1716,8 @@ GSPrivateCheckTasks()
NSLog(@"waitpid %d, termination status = %d",
result, status);
#endif
[self _terminatedChild: WTERMSIG(status)];
[self _terminatedChild: WTERMSIG(status)
reason: NSTaskTerminationReasonUncaughtSignal];
}
else
{

View file

@ -49,6 +49,8 @@ int main()
[task setArguments: args];
[task launch];
[task waitUntilExit];
PASS([task terminationReason] == NSTaskTerminationReasonExit,
"termination reason for normal exit works");
[arp release]; arp = nil;
return 0;

View file

@ -6,7 +6,7 @@
#import <Foundation/NSRunLoop.h>
#import <Foundation/NSAutoreleasePool.h>
#import "ObjectTesting.h"
#import "ObjectTesting.h"
@interface TaskHandler : NSObject
{
@ -16,74 +16,81 @@
@implementation TaskHandler
static BOOL taskTerminationNotificationReceived;
static BOOL taskTerminationNotificationReceived;
- (void) setLaunchPath: (NSString*)s
{
ASSIGNCOPY(path, s);
}
- (void) taskDidTerminate: (NSNotification *)notification
{
NSLog(@"Received NSTaskDidTerminateNotification %@", notification);
taskTerminationNotificationReceived = YES;
}
- (void) taskDidTerminate: (NSNotification *)notification
{
NSLog(@"Received NSTaskDidTerminateNotification %@", notification);
taskTerminationNotificationReceived = YES;
}
- (void) testNSTaskNotifications
{
NSDate *deadline;
BOOL earlyTermination = NO;
- (void) testNSTaskNotifications
{
NSDate *deadline;
BOOL earlyTermination = NO;
for (;;)
{
NSTask *task = [NSTask new];
{
NSTask *task = [NSTask new];
[task setLaunchPath: path];
[task setArguments: [NSArray arrayWithObjects:
@"-c", @"echo Child starting; sleep 10; echo Child exiting", nil]];
taskTerminationNotificationReceived = NO;
@"-c", @"echo Child starting; sleep 10; echo Child exiting", nil]];
taskTerminationNotificationReceived = NO;
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(taskDidTerminate:)
name: NSTaskDidTerminateNotification
object: task];
[task launch];
NSLog(@"Launched pid %d", [task processIdentifier]);
addObserver: self
selector: @selector(taskDidTerminate:)
name: NSTaskDidTerminateNotification
object: task];
[task launch];
NSLog(@"Launched pid %d", [task processIdentifier]);
if (earlyTermination)
{
NSLog(@"Running run loop for 5 seconds");
deadline = [NSDate dateWithTimeIntervalSinceNow:5.0];
while ([deadline timeIntervalSinceNow] > 0.0)
{
NSLog(@"Running run loop for 5 seconds");
deadline = [NSDate dateWithTimeIntervalSinceNow:5.0];
while ([deadline timeIntervalSinceNow] > 0.0
&& !taskTerminationNotificationReceived)
{
[[NSRunLoop currentRunLoop]
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
NSLog(@"Run loop finished, will now call -[NSTask terminate]");
[task terminate];
NSLog(@"Terminate returned, waiting for termination");
[task waitUntilExit];
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
NSLog(@"Run loop finished, will now call -[NSTask terminate]");
[task terminate];
NSLog(@"Terminate returned, waiting for termination");
[task waitUntilExit];
PASS([task terminationReason]
== NSTaskTerminationReasonUncaughtSignal,
"termination reason for signal exit works");
}
}
else
{
NSLog(@"Running run loop for 15 seconds");
deadline = [NSDate dateWithTimeIntervalSinceNow: 15.0];
{
NSLog(@"Running run loop for 15 seconds");
deadline = [NSDate dateWithTimeIntervalSinceNow: 15.0];
while ([deadline timeIntervalSinceNow] > 0.0
&& !taskTerminationNotificationReceived)
&& !taskTerminationNotificationReceived)
{
[[NSRunLoop currentRunLoop]
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
}
}
[task release];
PASS([task terminationReason]
== NSTaskTerminationReasonExit,
"termination reason for normal exit works");
}
[task release];
NSAssert(taskTerminationNotificationReceived,
@"termination notification not received");
@"termination notification not received");
[[NSNotificationCenter defaultCenter]
removeObserver: self name: NSTaskDidTerminateNotification object: nil];
if (earlyTermination)
break;
earlyTermination = YES;
}
}
removeObserver: self name: NSTaskDidTerminateNotification object: nil];
if (earlyTermination)
break;
earlyTermination = YES;
}
}
@end