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:
Adam Fedor 1998-04-02 14:27:40 +00:00
parent 097ee73e95
commit a29048c198
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>
* aclocal.m4 (OBJC_CON_AUTOLOAD): Improved test. Check nm output

View file

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

View file

@ -30,6 +30,7 @@
#include <gnustep/base/fake-main.h>
@class NSArchiver;
@class NSArray;
@class NSCoder;
@class NSPortCoder;
@class NSMethodSignature;
@ -164,4 +165,19 @@ enum {NSNotFound = 0x7fffffff};
- performSelector: (SEL)aSelector withObject: object1 withObject: object2;
@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 */

View file

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

View file

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

View file

@ -271,6 +271,18 @@ static int debug_run_loop = 0;
@end
@interface NSRunLoop (TimedPerformers)
- (NSMutableArray*) _timedPerformers;
@end
@implementation NSRunLoop (TimedPerformers)
- (NSMutableArray*) _timedPerformers
{
return _timedPerformers;
}
@end
/*
* The RunLoopPerformer class is used to hold information about
* 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 argument;
unsigned order;
NSArray* modes;
NSArray *modes;
NSTimer *timer;
}
- (void) fire;
@ -296,12 +309,14 @@ static int debug_run_loop = 0;
argument: anArgument;
- (NSArray*) modes;
- (unsigned int) order;
- (void) setTimer: (NSTimer*)timer;
@end
@implementation RunLoopPerformer
- (void) dealloc
{
[timer invalidate];
[target release];
[argument release];
[modes release];
@ -310,7 +325,13 @@ static int debug_run_loop = 0;
- (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
@ -351,6 +372,91 @@ static int debug_run_loop = 0;
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
@ -362,6 +468,7 @@ static int debug_run_loop = 0;
- (RunLoopWatcher*) _getWatcher: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode;
- (NSMutableArray*) _performers;
- (void) _removeWatcher: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode;
@ -430,17 +537,20 @@ static int debug_run_loop = 0;
- (void) _checkPerformers
{
RunLoopPerformer *item;
int count = [_performers count];
NSArray *array = [NSArray arrayWithArray: _performers];
int count = [array count];
unsigned pos;
int i;
for (i = count; i > 0; i++) {
item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)];
for (i = 0; i < count; i++) {
item = (RunLoopPerformer*)[array objectAtIndex: i];
if ([[item modes] containsObject: _current_mode]) {
[item retain];
[_performers removeObjectAtIndex:(i-1)];
[item fire];
[item release];
pos = [_performers indexOfObjectIdenticalTo: item];
if (pos != NSNotFound) {
if ([[item modes] containsObject: _current_mode]) {
[_performers removeObjectAtIndex: pos];
[item fire];
}
}
}
}
@ -640,6 +750,7 @@ static int debug_run_loop = 0;
_mode_2_watchers = NSCreateMapTable (NSObjectMapKeyCallBacks,
NSObjectMapValueCallBacks, 0);
_performers = [[NSMutableArray arrayWithCapacity:8] retain];
_timedPerformers = [[NSMutableArray arrayWithCapacity:8] retain];
return self;
}
@ -648,6 +759,7 @@ static int debug_run_loop = 0;
NSFreeMapTable(_mode_2_timers);
NSFreeMapTable(_mode_2_watchers);
[_performers release];
[_timedPerformers release];
[super dealloc];
}
@ -1159,6 +1271,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
int count = [_performers count];
int i;
[target retain];
[argument retain];
for (i = count; i > 0; i++) {
item = (RunLoopPerformer*)[_performers objectAtIndex:(i-1)];
@ -1166,6 +1280,8 @@ id NSDefaultRunLoopMode = @"NSDefaultRunLoopMode";
[_performers removeObjectAtIndex:(i-1)];
}
}
[argument release];
[target release];
}
- (void) configureAsServer

View file

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

View file

@ -1,10 +1,12 @@
#include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSTask.h>
int
main()
{
id pool;
NSDictionary *env;
NSTask *task;
pool = [[NSAutoreleasePool alloc] init];
@ -14,6 +16,17 @@ main()
[task waitUntilExit];
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];
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
* thirty minutes.
* Remove any server from which we have had no messages in the last
* thirty minutes (as long as we have sent as probe in that time).
*/
static void
prb_tim(long when)
{
int i;
when -= 1800;
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);
}
}
@ -1524,10 +1525,10 @@ handle_request(int desc)
if (debug > 2) {
fprintf(stderr, "Probe from '%s'\n", inet_ntoa(sin));
}
prb_add(&sin);
net = inet_netof(sin);
ptr = (struct in_addr*)&r_info[desc].buf.r.name[2*IASIZE];
c = (r_info[desc].buf.r.nsize - 2*IASIZE)/IASIZE;
prb_add(&sin);
while (c-- > 0) {
if (debug > 2) {
fprintf(stderr, "Delete server '%s'\n", inet_ntoa(*ptr));
@ -1535,6 +1536,12 @@ handle_request(int desc)
prb_del(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
@ -1611,10 +1618,10 @@ handle_request(int desc)
if (debug > 2) {
fprintf(stderr, "Probe reply from '%s'\n", inet_ntoa(sin));
}
prb_add(&sin);
net = inet_netof(sin);
ptr = (struct in_addr*)&r_info[desc].buf.r.name[2*IASIZE];
c = (r_info[desc].buf.r.nsize - 2*IASIZE)/IASIZE;
prb_add(&sin);
while (c-- > 0) {
if (debug > 2) {
fprintf(stderr, "Delete server '%s'\n", inet_ntoa(*ptr));
@ -1622,6 +1629,12 @@ handle_request(int desc)
prb_del(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