mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
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:
parent
35962654cb
commit
04406427e3
5 changed files with 122 additions and 53 deletions
|
@ -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>
|
2016-06-25 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSMessagePort.m:
|
* Source/NSMessagePort.m:
|
||||||
|
|
|
@ -36,6 +36,14 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
@interface NSTask : NSObject
|
||||||
{
|
{
|
||||||
#if GS_EXPOSE(NSTask)
|
#if GS_EXPOSE(NSTask)
|
||||||
|
@ -53,6 +61,7 @@ extern "C" {
|
||||||
BOOL _hasTerminated;
|
BOOL _hasTerminated;
|
||||||
BOOL _hasCollected;
|
BOOL _hasCollected;
|
||||||
BOOL _hasNotified;
|
BOOL _hasNotified;
|
||||||
|
NSTaskTerminationReason _terminationReason;
|
||||||
#endif
|
#endif
|
||||||
#if GS_NONFRAGILE
|
#if GS_NONFRAGILE
|
||||||
#else
|
#else
|
||||||
|
@ -97,6 +106,9 @@ extern "C" {
|
||||||
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
|
#if OS_API_VERSION(GS_API_MACOSX, GS_API_LATEST)
|
||||||
- (int) processIdentifier;
|
- (int) processIdentifier;
|
||||||
#endif
|
#endif
|
||||||
|
#if OS_API_VERSION(MAC_OS_X_VERSION_10_5,GS_API_LATEST)
|
||||||
|
- (NSTaskTerminationReason) terminationReason;
|
||||||
|
#endif
|
||||||
- (int) terminationStatus;
|
- (int) terminationStatus;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -118,6 +118,10 @@ static void handleSignal(int sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#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
|
@interface NSConcreteWindowsTask : NSTask
|
||||||
{
|
{
|
||||||
@public
|
@public
|
||||||
|
@ -222,7 +226,7 @@ pty_slave(const char* name)
|
||||||
@interface NSTask (Private)
|
@interface NSTask (Private)
|
||||||
- (NSString *) _fullLaunchPath;
|
- (NSString *) _fullLaunchPath;
|
||||||
- (void) _collectChild;
|
- (void) _collectChild;
|
||||||
- (void) _terminatedChild: (int)status;
|
- (void) _terminatedChild: (int)status reason: (NSTaskTerminationReason)reason;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
|
@ -673,6 +677,30 @@ pty_slave(const char* name)
|
||||||
#endif
|
#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 />
|
* Returns the termination status of the task.<br />
|
||||||
* If the task has not completed running, raises an
|
* If the task has not completed running, raises an
|
||||||
|
@ -876,13 +904,14 @@ pty_slave(const char* name)
|
||||||
[self subclassResponsibility: _cmd];
|
[self subclassResponsibility: _cmd];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) _terminatedChild: (int)status
|
- (void) _terminatedChild: (int)status reason: (NSTaskTerminationReason)reason
|
||||||
{
|
{
|
||||||
[tasksLock lock];
|
[tasksLock lock];
|
||||||
IF_NO_GC([[self retain] autorelease];)
|
IF_NO_GC([[self retain] autorelease];)
|
||||||
NSMapRemove(activeTasks, (void*)(intptr_t)_taskId);
|
NSMapRemove(activeTasks, (void*)(intptr_t)_taskId);
|
||||||
[tasksLock unlock];
|
[tasksLock unlock];
|
||||||
_terminationStatus = status;
|
_terminationStatus = status;
|
||||||
|
_terminationReason = reason;
|
||||||
_hasCollected = YES;
|
_hasCollected = YES;
|
||||||
_hasTerminated = YES;
|
_hasTerminated = YES;
|
||||||
if (_hasNotified == NO)
|
if (_hasNotified == NO)
|
||||||
|
@ -930,7 +959,9 @@ GSPrivateCheckTasks()
|
||||||
{
|
{
|
||||||
if (eCode != STILL_ACTIVE)
|
if (eCode != STILL_ACTIVE)
|
||||||
{
|
{
|
||||||
[t _terminatedChild: eCode];
|
[t _terminatedChild: eCode reason: (WIN_SIGNALLED == eCode)
|
||||||
|
? NSTaskTerminationReasonUncaughtSignal
|
||||||
|
: NSTaskTerminationReasonExit];
|
||||||
found = YES;
|
found = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -972,8 +1003,11 @@ GSPrivateCheckTasks()
|
||||||
return;
|
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;
|
_hasTerminated = YES;
|
||||||
TerminateProcess(procInfo.hProcess, 10);
|
TerminateProcess(procInfo.hProcess, WIN_SIGNALLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1307,7 +1341,9 @@ quotedFromString(NSString *aString)
|
||||||
}
|
}
|
||||||
else if (eCode != STILL_ACTIVE)
|
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",
|
NSLog(@"waitpid %d, exit status = %d",
|
||||||
result, status);
|
result, status);
|
||||||
#endif
|
#endif
|
||||||
[t _terminatedChild: WEXITSTATUS(status)];
|
[t _terminatedChild: WEXITSTATUS(status)
|
||||||
|
reason: NSTaskTerminationReasonExit];
|
||||||
found = YES;
|
found = YES;
|
||||||
}
|
}
|
||||||
else if (WIFSIGNALED(status))
|
else if (WIFSIGNALED(status))
|
||||||
|
@ -1373,7 +1410,8 @@ GSPrivateCheckTasks()
|
||||||
NSLog(@"waitpid %d, termination status = %d",
|
NSLog(@"waitpid %d, termination status = %d",
|
||||||
result, status);
|
result, status);
|
||||||
#endif
|
#endif
|
||||||
[t _terminatedChild: WTERMSIG(status)];
|
[t _terminatedChild: WTERMSIG(status)
|
||||||
|
reason: NSTaskTerminationReasonUncaughtSignal];
|
||||||
found = YES;
|
found = YES;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1669,7 +1707,8 @@ GSPrivateCheckTasks()
|
||||||
NSLog(@"waitpid %d, exit status = %d",
|
NSLog(@"waitpid %d, exit status = %d",
|
||||||
result, status);
|
result, status);
|
||||||
#endif
|
#endif
|
||||||
[self _terminatedChild: WEXITSTATUS(status)];
|
[self _terminatedChild: WEXITSTATUS(status)
|
||||||
|
reason: NSTaskTerminationReasonExit];
|
||||||
}
|
}
|
||||||
else if (WIFSIGNALED(status))
|
else if (WIFSIGNALED(status))
|
||||||
{
|
{
|
||||||
|
@ -1677,7 +1716,8 @@ GSPrivateCheckTasks()
|
||||||
NSLog(@"waitpid %d, termination status = %d",
|
NSLog(@"waitpid %d, termination status = %d",
|
||||||
result, status);
|
result, status);
|
||||||
#endif
|
#endif
|
||||||
[self _terminatedChild: WTERMSIG(status)];
|
[self _terminatedChild: WTERMSIG(status)
|
||||||
|
reason: NSTaskTerminationReasonUncaughtSignal];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -49,6 +49,8 @@ int main()
|
||||||
[task setArguments: args];
|
[task setArguments: args];
|
||||||
[task launch];
|
[task launch];
|
||||||
[task waitUntilExit];
|
[task waitUntilExit];
|
||||||
|
PASS([task terminationReason] == NSTaskTerminationReasonExit,
|
||||||
|
"termination reason for normal exit works");
|
||||||
|
|
||||||
[arp release]; arp = nil;
|
[arp release]; arp = nil;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#import <Foundation/NSRunLoop.h>
|
#import <Foundation/NSRunLoop.h>
|
||||||
#import <Foundation/NSAutoreleasePool.h>
|
#import <Foundation/NSAutoreleasePool.h>
|
||||||
|
|
||||||
#import "ObjectTesting.h"
|
#import "ObjectTesting.h"
|
||||||
|
|
||||||
@interface TaskHandler : NSObject
|
@interface TaskHandler : NSObject
|
||||||
{
|
{
|
||||||
|
@ -16,74 +16,81 @@
|
||||||
|
|
||||||
@implementation TaskHandler
|
@implementation TaskHandler
|
||||||
|
|
||||||
static BOOL taskTerminationNotificationReceived;
|
static BOOL taskTerminationNotificationReceived;
|
||||||
|
|
||||||
- (void) setLaunchPath: (NSString*)s
|
- (void) setLaunchPath: (NSString*)s
|
||||||
{
|
{
|
||||||
ASSIGNCOPY(path, s);
|
ASSIGNCOPY(path, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) taskDidTerminate: (NSNotification *)notification
|
- (void) taskDidTerminate: (NSNotification *)notification
|
||||||
{
|
{
|
||||||
NSLog(@"Received NSTaskDidTerminateNotification %@", notification);
|
NSLog(@"Received NSTaskDidTerminateNotification %@", notification);
|
||||||
taskTerminationNotificationReceived = YES;
|
taskTerminationNotificationReceived = YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) testNSTaskNotifications
|
- (void) testNSTaskNotifications
|
||||||
{
|
{
|
||||||
NSDate *deadline;
|
NSDate *deadline;
|
||||||
BOOL earlyTermination = NO;
|
BOOL earlyTermination = NO;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
NSTask *task = [NSTask new];
|
NSTask *task = [NSTask new];
|
||||||
|
|
||||||
[task setLaunchPath: path];
|
[task setLaunchPath: path];
|
||||||
[task setArguments: [NSArray arrayWithObjects:
|
[task setArguments: [NSArray arrayWithObjects:
|
||||||
@"-c", @"echo Child starting; sleep 10; echo Child exiting", nil]];
|
@"-c", @"echo Child starting; sleep 10; echo Child exiting", nil]];
|
||||||
taskTerminationNotificationReceived = NO;
|
taskTerminationNotificationReceived = NO;
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
addObserver: self
|
addObserver: self
|
||||||
selector: @selector(taskDidTerminate:)
|
selector: @selector(taskDidTerminate:)
|
||||||
name: NSTaskDidTerminateNotification
|
name: NSTaskDidTerminateNotification
|
||||||
object: task];
|
object: task];
|
||||||
[task launch];
|
[task launch];
|
||||||
NSLog(@"Launched pid %d", [task processIdentifier]);
|
NSLog(@"Launched pid %d", [task processIdentifier]);
|
||||||
if (earlyTermination)
|
if (earlyTermination)
|
||||||
{
|
{
|
||||||
NSLog(@"Running run loop for 5 seconds");
|
NSLog(@"Running run loop for 5 seconds");
|
||||||
deadline = [NSDate dateWithTimeIntervalSinceNow:5.0];
|
deadline = [NSDate dateWithTimeIntervalSinceNow:5.0];
|
||||||
while ([deadline timeIntervalSinceNow] > 0.0)
|
while ([deadline timeIntervalSinceNow] > 0.0
|
||||||
|
&& !taskTerminationNotificationReceived)
|
||||||
{
|
{
|
||||||
[[NSRunLoop currentRunLoop]
|
[[NSRunLoop currentRunLoop]
|
||||||
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
|
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
|
||||||
NSLog(@"Run loop finished, will now call -[NSTask terminate]");
|
NSLog(@"Run loop finished, will now call -[NSTask terminate]");
|
||||||
[task terminate];
|
[task terminate];
|
||||||
NSLog(@"Terminate returned, waiting for termination");
|
NSLog(@"Terminate returned, waiting for termination");
|
||||||
[task waitUntilExit];
|
[task waitUntilExit];
|
||||||
|
PASS([task terminationReason]
|
||||||
|
== NSTaskTerminationReasonUncaughtSignal,
|
||||||
|
"termination reason for signal exit works");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NSLog(@"Running run loop for 15 seconds");
|
NSLog(@"Running run loop for 15 seconds");
|
||||||
deadline = [NSDate dateWithTimeIntervalSinceNow: 15.0];
|
deadline = [NSDate dateWithTimeIntervalSinceNow: 15.0];
|
||||||
while ([deadline timeIntervalSinceNow] > 0.0
|
while ([deadline timeIntervalSinceNow] > 0.0
|
||||||
&& !taskTerminationNotificationReceived)
|
&& !taskTerminationNotificationReceived)
|
||||||
{
|
{
|
||||||
[[NSRunLoop currentRunLoop]
|
[[NSRunLoop currentRunLoop]
|
||||||
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
|
runUntilDate: [NSDate dateWithTimeIntervalSinceNow: 1.0]];
|
||||||
}
|
}
|
||||||
}
|
PASS([task terminationReason]
|
||||||
[task release];
|
== NSTaskTerminationReasonExit,
|
||||||
|
"termination reason for normal exit works");
|
||||||
|
}
|
||||||
|
[task release];
|
||||||
NSAssert(taskTerminationNotificationReceived,
|
NSAssert(taskTerminationNotificationReceived,
|
||||||
@"termination notification not received");
|
@"termination notification not received");
|
||||||
[[NSNotificationCenter defaultCenter]
|
[[NSNotificationCenter defaultCenter]
|
||||||
removeObserver: self name: NSTaskDidTerminateNotification object: nil];
|
removeObserver: self name: NSTaskDidTerminateNotification object: nil];
|
||||||
if (earlyTermination)
|
if (earlyTermination)
|
||||||
break;
|
break;
|
||||||
earlyTermination = YES;
|
earlyTermination = YES;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue