Fixes from Frith-MacDonald.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2781 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fedor 1998-04-02 14:27:40 +00:00
parent 3c756dba20
commit 06be886653
9 changed files with 229 additions and 30 deletions

View file

@ -1,3 +1,34 @@
Wed Apr 1 18:45:00 1998 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* Tools/gdomap.m: Modified code so that we make sure we have at least
one valid route to any gdomap process which has probed us. This is
to cope with machines which send out info about all their interfaces
when one or more of the interfaces is not working.
* src/checks/nstask.m: added test for environment setting.
* src/NSCalendarDate.m: Fixed bug in initialisation where daylight
savings time is in operation - was adjusting in wrong direction.
* src/NSRunLoop.m: Added NSObject catagory for the methods -
([NSObject +cancelPreviousPerformRequestsWithTarget:selector:object:]),
([NSObject -performSelector:withObject:afterDelay:]), and
([NSObject -performSelector:withObject:afterDelay:inModes:])
* src/NSTask.m: Various bug fixes as a result of running the test
suite. All seems to work ok now.
* src/NSDate.h: Changed order of declaractions so this can be included
within NSObject.h
* src/NSObject.h: Added run-loop integration methods -
([NSObject +cancelPreviousPerformRequestsWithTarget:selector:object:]),
([NSObject -performSelector:withObject:afterDelay:]), and
([NSObject -performSelector:withObject:afterDelay:inModes:])
* src/NSRunLoop.h: Added an instance variable to keep track of
queued delayed actions to be performed on objects.
Tue Mar 31 11:32:03 1998 Adam Fedor <fedor@doc.com> Tue Mar 31 11:32:03 1998 Adam Fedor <fedor@doc.com>
* aclocal.m4 (OBJC_CON_AUTOLOAD): Improved test. Check nm output * aclocal.m4 (OBJC_CON_AUTOLOAD): Improved test. Check nm output

View file

@ -21,11 +21,11 @@
#ifndef __NSDate_h_GNUSTEP_BASE_INCLUDE #ifndef __NSDate_h_GNUSTEP_BASE_INCLUDE
#define __NSDate_h_GNUSTEP_BASE_INCLUDE #define __NSDate_h_GNUSTEP_BASE_INCLUDE
#include <Foundation/NSObject.h>
/* Time interval difference between two dates, in seconds. */ /* Time interval difference between two dates, in seconds. */
typedef double NSTimeInterval; typedef double NSTimeInterval;
#include <Foundation/NSObject.h>
@class NSArray; @class NSArray;
@class NSCalendarDate; @class NSCalendarDate;
@class NSDictionary; @class NSDictionary;

View file

@ -30,6 +30,7 @@
#include <gnustep/base/fake-main.h> #include <gnustep/base/fake-main.h>
@class NSArchiver; @class NSArchiver;
@class NSArray;
@class NSCoder; @class NSCoder;
@class NSPortCoder; @class NSPortCoder;
@class NSMethodSignature; @class NSMethodSignature;
@ -164,4 +165,19 @@ enum {NSNotFound = 0x7fffffff};
- performSelector: (SEL)aSelector withObject: object1 withObject: object2; - performSelector: (SEL)aSelector withObject: object1 withObject: object2;
@end @end
#include <Foundation/NSDate.h>
@interface NSObject (TimedPerformers)
+ (void) cancelPreviousPerformRequestsWithTarget: (id)obj
selector: (SEL)s
object: (id)arg;
- (void) performSelector: (SEL)s
withObject: (id)arg
afterDelay: (NSTimeInterval)seconds;
- (void) performSelector: (SEL)s
withObject: (id)arg
afterDelay: (NSTimeInterval)seconds
inModes: (NSArray*)modes;
@end
#endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */ #endif /* __NSObject_h_GNUSTEP_BASE_INCLUDE */

View file

@ -38,6 +38,7 @@ extern id NSDefaultRunLoopMode;
@private NSMapTable *_mode_2_timers; @private NSMapTable *_mode_2_timers;
@private NSMapTable *_mode_2_watchers; @private NSMapTable *_mode_2_watchers;
@private NSMutableArray *_performers; @private NSMutableArray *_performers;
@private NSMutableArray *_timedPerformers;
} }
+ (NSRunLoop*) currentRunLoop; + (NSRunLoop*) currentRunLoop;

View file

@ -525,7 +525,7 @@ static id long_day[7] = {@"Sunday",
oldOffset = [time_zone timeZoneSecondsFromGMT]; oldOffset = [time_zone timeZoneSecondsFromGMT];
time_zone = z; time_zone = z;
newOffset = [time_zone timeZoneSecondsFromGMT]; newOffset = [time_zone timeZoneSecondsFromGMT];
s += oldOffset - newOffset; s += newOffset - oldOffset;
} }
else else
{ {

View file

@ -271,6 +271,18 @@ static int debug_run_loop = 0;
@end @end
@interface NSRunLoop (TimedPerformers)
- (NSMutableArray*) _timedPerformers;
@end
@implementation NSRunLoop (TimedPerformers)
- (NSMutableArray*) _timedPerformers
{
return _timedPerformers;
}
@end
/* /*
* The RunLoopPerformer class is used to hold information about * The RunLoopPerformer class is used to hold information about
* messages which are due to be sent to objects once a particular * messages which are due to be sent to objects once a particular
@ -282,7 +294,8 @@ static int debug_run_loop = 0;
id target; id target;
id argument; id argument;
unsigned order; unsigned order;
NSArray* modes; NSArray *modes;
NSTimer *timer;
} }
- (void) fire; - (void) fire;
@ -296,12 +309,14 @@ static int debug_run_loop = 0;
argument: anArgument; argument: anArgument;
- (NSArray*) modes; - (NSArray*) modes;
- (unsigned int) order; - (unsigned int) order;
- (void) setTimer: (NSTimer*)timer;
@end @end
@implementation RunLoopPerformer @implementation RunLoopPerformer
- (void) dealloc - (void) dealloc
{ {
[timer invalidate];
[target release]; [target release];
[argument release]; [argument release];
[modes release]; [modes release];
@ -310,7 +325,13 @@ static int debug_run_loop = 0;
- (void)fire - (void)fire
{ {
[target perform:selector withObject:argument]; if (timer != nil) {
timer = nil;
[[self retain] autorelease];
[[[NSRunLoop currentInstance] _timedPerformers]
removeObjectIdenticalTo: self];
}
[target perform: selector withObject: argument];
} }
- initWithSelector: (SEL)aSelector - initWithSelector: (SEL)aSelector
@ -351,6 +372,91 @@ static int debug_run_loop = 0;
return order; return order;
} }
- (void) setTimer: (NSTimer*)t
{
timer = t;
}
@end
@implementation NSObject (TimedPerformers)
+ (void) cancelPreviousPerformRequestsWithTarget: (id)target
selector: (SEL)aSelector
object: (id)arg
{
NSMutableArray *array;
int i;
[target retain];
[arg retain];
array = [[NSRunLoop currentInstance] _timedPerformers];
for (i = [array count]; i > 0; i--) {
if ([[array objectAtIndex: i-1] matchesSelector: aSelector
target: target
argument: arg]) {
[array removeObjectAtIndex: i-1];
}
}
[arg release];
[target release];
}
- (void) performSelector: (SEL)aSelector
withObject: (id)argument
afterDelay: (NSTimeInterval)seconds
{
NSMutableArray *array;
RunLoopPerformer *item;
array = [[NSRunLoop currentInstance] _timedPerformers];
item = [[RunLoopPerformer alloc] initWithSelector: aSelector
target: self
argument: argument
order: 0
modes: nil];
[array addObject: item];
[item setTimer: [NSTimer scheduledTimerWithTimeInterval: seconds
target: item
selector: @selector(fire)
userInfo: nil
repeats: NO]];
[item release];
}
- (void) performSelector: (SEL)aSelector
withObject: (id)argument
afterDelay: (NSTimeInterval)seconds
inModes: (NSArray*)modes
{
NSRunLoop *loop;
NSMutableArray *array;
RunLoopPerformer *item;
NSTimer *timer;
int i;
if (modes == nil || [modes count] == 0) {
return;
}
loop = [NSRunLoop currentInstance];
array = [loop _timedPerformers];
item = [[RunLoopPerformer alloc] initWithSelector: aSelector
target: self
argument: argument
order: 0
modes: nil];
[array addObject: item];
timer = [NSTimer timerWithTimeInterval: seconds
target: item
selector: @selector(fire)
userInfo: nil
repeats: NO];
[item setTimer: timer];
[item release];
for (i = 0; i < [modes count]; i++) {
[loop addTimer: timer forMode: [modes objectAtIndex: i]];
}
}
@end @end
@ -362,6 +468,7 @@ static int debug_run_loop = 0;
- (RunLoopWatcher*) _getWatcher: (void*)data - (RunLoopWatcher*) _getWatcher: (void*)data
type: (RunLoopEventType)type type: (RunLoopEventType)type
forMode: (NSString*)mode; forMode: (NSString*)mode;
- (NSMutableArray*) _performers;
- (void) _removeWatcher: (void*)data - (void) _removeWatcher: (void*)data
type: (RunLoopEventType)type type: (RunLoopEventType)type
forMode: (NSString*)mode; forMode: (NSString*)mode;
@ -430,17 +537,20 @@ static int debug_run_loop = 0;
- (void) _checkPerformers - (void) _checkPerformers
{ {
RunLoopPerformer *item; RunLoopPerformer *item;
int count = [_performers count]; NSArray *array = [NSArray arrayWithArray: _performers];
int count = [array count];
unsigned pos;
int i; int i;
for (i = count; i > 0; i++) { for (i = 0; i < count; i++) {
item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)]; item = (RunLoopPerformer*)[array objectAtIndex: i];
if ([[item modes] containsObject: _current_mode]) { pos = [_performers indexOfObjectIdenticalTo: item];
[item retain]; if (pos != NSNotFound) {
[_performers removeObjectAtIndex:(i-1)]; if ([[item modes] containsObject: _current_mode]) {
[item fire]; [_performers removeObjectAtIndex: pos];
[item release]; [item fire];
}
} }
} }
} }
@ -640,6 +750,7 @@ static int debug_run_loop = 0;
_mode_2_watchers = NSCreateMapTable (NSObjectMapKeyCallBacks, _mode_2_watchers = NSCreateMapTable (NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 0); NSObjectMapValueCallBacks, 0);
_performers = [[NSMutableArray arrayWithCapacity:8] retain]; _performers = [[NSMutableArray arrayWithCapacity:8] retain];
_timedPerformers = [[NSMutableArray arrayWithCapacity:8] retain];
return self; return self;
} }
@ -648,6 +759,7 @@ static int debug_run_loop = 0;
NSFreeMapTable(_mode_2_timers); NSFreeMapTable(_mode_2_timers);
NSFreeMapTable(_mode_2_watchers); NSFreeMapTable(_mode_2_watchers);
[_performers release]; [_performers release];
[_timedPerformers release];
[super dealloc]; [super dealloc];
} }
@ -1159,6 +1271,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
int count = [_performers count]; int count = [_performers count];
int i; int i;
[target retain];
[argument retain];
for (i = count; i > 0; i++) { for (i = count; i > 0; i++) {
item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)]; item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)];
@ -1166,6 +1280,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
[_performers removeObjectAtIndex:(i-1)]; [_performers removeObjectAtIndex:(i-1)];
} }
} }
[argument release];
[target release];
} }
- (void) configureAsServer - (void) configureAsServer

View file

@ -218,7 +218,7 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
if (hasCollected == NO) { if (hasCollected == NO) {
[self _collectChild]; [self _collectChild];
} }
if (hasTerminated == NO) return NO; if (hasTerminated == YES) return NO;
return YES; return YES;
} }
@ -231,7 +231,7 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
if (hasCollected == NO) { if (hasCollected == NO) {
[self _collectChild]; [self _collectChild];
} }
if (hasTerminated) { if (hasTerminated == NO) {
[NSException raise: NSInvalidArgumentException [NSException raise: NSInvalidArgumentException
format: @"NSTask - task has not yet terminated"]; format: @"NSTask - task has not yet terminated"];
} }
@ -259,7 +259,7 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
int ec = [e count]; int ec = [e count];
int ac = [a count]; int ac = [a count];
const char *args[ac+2]; const char *args[ac+2];
const char *envp[ec+1]; const char *envl[ec+1];
int i; int i;
if (hasLaunched) { if (hasLaunched) {
@ -287,12 +287,18 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
for (i = 0; i < ec; i++) { for (i = 0; i < ec; i++) {
NSString *s; NSString *s;
id key = [k objectAtIndex: i]; id key = [k objectAtIndex: i];
id val = [e objectForKey: k]; id val = [e objectForKey: key];
s = [NSString stringWithFormat: @"%s=%s", [key cString], [val cString]]; if (val) {
envp[i] = [s cString]; s = [NSString stringWithFormat: @"%s=%s",
[key cString], [val cString]];
}
else {
s = [NSString stringWithFormat: @"%s=", [key cString]];
}
envl[i] = [s cString];
} }
envp[ec] = 0; envl[ec] = 0;
path = [[self currentDirectoryPath] cString]; path = [[self currentDirectoryPath] cString];
idesc = [[self standardInput] fileDescriptor]; idesc = [[self standardInput] fileDescriptor];
@ -309,7 +315,7 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
if (odesc != 1) dup2(odesc, 1); if (odesc != 1) dup2(odesc, 1);
if (edesc != 2) dup2(edesc, 2); if (edesc != 2) dup2(edesc, 2);
chdir(path); chdir(path);
execve(executable, args, envp); execve(executable, args, envl);
exit(-1); exit(-1);
} }
else { else {
@ -358,10 +364,13 @@ NSString *NSTaskDidTerminateNotification = @"NSTaskDidTerminateNotification";
{ {
if (hasCollected == NO) { if (hasCollected == NO) {
if (waitpid(taskId, &terminationStatus, WNOHANG) == taskId) { if (waitpid(taskId, &terminationStatus, WNOHANG) == taskId) {
hasCollected = YES; if (WIFEXITED(terminationStatus)) {
hasTerminated = YES; terminationStatus = WEXITSTATUS(terminationStatus);
if (hasNotified == NO) { hasCollected = YES;
[self _sendNotification]; hasTerminated = YES;
if (hasNotified == NO) {
[self _sendNotification];
}
} }
} }
} }

View file

@ -1,10 +1,12 @@
#include <Foundation/NSAutoreleasePool.h> #include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSTask.h> #include <Foundation/NSTask.h>
int int
main() main()
{ {
id pool; id pool;
NSDictionary *env;
NSTask *task; NSTask *task;
pool = [[NSAutoreleasePool alloc] init]; pool = [[NSAutoreleasePool alloc] init];
@ -14,6 +16,17 @@ main()
[task waitUntilExit]; [task waitUntilExit];
printf("Exit status - %d\n", [task terminationStatus]); printf("Exit status - %d\n", [task terminationStatus]);
[pool release];
pool = [[NSAutoreleasePool alloc] init];
task = [NSTask new];
env = [[[[NSProcessInfo processInfo] environment] mutableCopy] autorelease];
[task setEnvironment: env];
[task setLaunchPath: @"/bin/sh"];
[task setArguments: [NSArray arrayWithObjects: @"-c", @"echo $PATH", nil]];
[task launch];
[task waitUntilExit];
[task release];
[pool release]; [pool release];
exit(0); exit(0);

View file

@ -537,16 +537,17 @@ prb_del(struct in_addr *p)
} }
/* /*
* Remove any server from which we have had no messages in the last * Remove any server from which we have had no messages in the last
* thirty minutes. * thirty minutes (as long as we have sent as probe in that time).
*/ */
static void static void
prb_tim(long when) prb_tim(long when)
{ {
int i; int i;
when -= 1800;
for (i = prb_used - 1; i >= 0; i--) { for (i = prb_used - 1; i >= 0; i--) {
if (when - prb[i]->when > 1800) { if (prb[i]->when < when && prb[i]->when < last_probe) {
prb_del(&prb[i]->sin); prb_del(&prb[i]->sin);
} }
} }
@ -1524,10 +1525,10 @@ handle_request(int desc)
if (debug > 2) { if (debug > 2) {
fprintf(stderr, "Probe from '%s'\n", inet_ntoa(sin)); fprintf(stderr, "Probe from '%s'\n", inet_ntoa(sin));
} }
prb_add(&sin);
net = inet_netof(sin); net = inet_netof(sin);
ptr = (struct in_addr*)&r_info[desc].buf.r.name[2*IASIZE]; ptr = (struct in_addr*)&r_info[desc].buf.r.name[2*IASIZE];
c = (r_info[desc].buf.r.nsize - 2*IASIZE)/IASIZE; c = (r_info[desc].buf.r.nsize - 2*IASIZE)/IASIZE;
prb_add(&sin);
while (c-- > 0) { while (c-- > 0) {
if (debug > 2) { if (debug > 2) {
fprintf(stderr, "Delete server '%s'\n", inet_ntoa(*ptr)); fprintf(stderr, "Delete server '%s'\n", inet_ntoa(*ptr));
@ -1535,6 +1536,12 @@ handle_request(int desc)
prb_del(ptr); prb_del(ptr);
ptr++; ptr++;
} }
/*
* Irrespective of what we are told to do - we also add the
* interface from which this packet arrived so we have a
* route we KNOW we can use.
*/
prb_add(&r_info[desc].addr.sin_addr);
} }
/* /*
* For a UDP request from another name server, we send a reply * For a UDP request from another name server, we send a reply
@ -1611,10 +1618,10 @@ handle_request(int desc)
if (debug > 2) { if (debug > 2) {
fprintf(stderr, "Probe reply from '%s'\n", inet_ntoa(sin)); fprintf(stderr, "Probe reply from '%s'\n", inet_ntoa(sin));
} }
prb_add(&sin);
net = inet_netof(sin); net = inet_netof(sin);
ptr = (struct in_addr*)&r_info[desc].buf.r.name[2*IASIZE]; ptr = (struct in_addr*)&r_info[desc].buf.r.name[2*IASIZE];
c = (r_info[desc].buf.r.nsize - 2*IASIZE)/IASIZE; c = (r_info[desc].buf.r.nsize - 2*IASIZE)/IASIZE;
prb_add(&sin);
while (c-- > 0) { while (c-- > 0) {
if (debug > 2) { if (debug > 2) {
fprintf(stderr, "Delete server '%s'\n", inet_ntoa(*ptr)); fprintf(stderr, "Delete server '%s'\n", inet_ntoa(*ptr));
@ -1622,6 +1629,12 @@ handle_request(int desc)
prb_del(ptr); prb_del(ptr);
ptr++; ptr++;
} }
/*
* Irrespective of what we are told to do - we also add the
* interface from which this packet arrived so we have a
* route we KNOW we can use.
*/
prb_add(&r_info[desc].addr.sin_addr);
} }
/* /*
* Because this is really a reply to us, we don't want to reply * Because this is really a reply to us, we don't want to reply