mproved task handling under windoze.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@13229 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
CaS 2002-03-25 10:54:59 +00:00
parent f53e056e90
commit 564eba5338
4 changed files with 116 additions and 46 deletions

View file

@ -1,7 +1,10 @@
2002-03-25 Richard Frith-Macdonald <rfm@gnu.org> 2002-03-25 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSTask.m: GSCheckTasks() return NO under MINGW - * Source/NSTask.m: Implement code to watch for child process exit
temporary hack to avoid busy wait in run loop. under mingw and rewrite various methods to handle process
termination nicely under windoze.
* Source/NSException.m: flush stderr ... under windoze stderr is
not automatically flushed!
2002-03-22 Richard Frith-Macdonald <rfm@gnu.org> 2002-03-22 Richard Frith-Macdonald <rfm@gnu.org>

View file

@ -49,6 +49,7 @@ _NSFoundationUncaughtExceptionHandler (NSException *exception)
_NSUncaughtExceptionHandler = _preventRecursion; _NSUncaughtExceptionHandler = _preventRecursion;
fprintf(stderr, "Uncaught exception %s, reason: %s\n", fprintf(stderr, "Uncaught exception %s, reason: %s\n",
[[exception name] lossyCString], [[exception reason] lossyCString]); [[exception name] lossyCString], [[exception reason] lossyCString]);
fflush(stderr); /* NEEDED UNDER MINGW */
/* FIXME: need to implement this: /* FIXME: need to implement this:
NSLogError("Uncaught exception %@, reason: %@", NSLogError("Uncaught exception %@, reason: %@",
[exception name], [exception reason]); [exception name], [exception reason]);

View file

@ -115,7 +115,9 @@ static void handleSignal(int sig)
#ifdef __MINGW__ #ifdef __MINGW__
@interface NSConcreteWindowsTask : NSTask @interface NSConcreteWindowsTask : NSTask
{ {
PROCESS_INFORMATION proc_info; @public
PROCESS_INFORMATION procInfo;
HANDLE wThread;
} }
@end @end
#define NSConcreteTask NSConcreteWindowsTask #define NSConcreteTask NSConcreteWindowsTask
@ -905,17 +907,51 @@ pty_slave(const char* name)
BOOL BOOL
GSCheckTasks() GSCheckTasks()
{ {
/* FIXME: Implement */ BOOL found = NO;
return NO;
if (hadChildSignal == YES)
{
NSArray *a;
unsigned c;
hadChildSignal = NO;
[tasksLock lock];
a = NSAllMapTableValues(activeTasks);
[tasksLock unlock];
c = [a count];
while (c-- > 0)
{
NSConcreteWindowsTask *t = [a objectAtIndex: c];
DWORD eCode;
if (GetExitCodeProcess(t->procInfo.hProcess, &eCode) != 0)
{
if (eCode != STILL_ACTIVE)
{
[t _terminatedChild: eCode];
found = YES;
}
}
}
}
return found;
} }
- (void) gcFinalize - (void) gcFinalize
{ {
[super gcFinalize]; [super gcFinalize];
if (proc_info.hProcess != NULL) if (wThread != NULL)
CloseHandle(proc_info.hProcess); {
if (proc_info.hThread != NULL) CloseHandle(wThread);
CloseHandle(proc_info.hThread); }
if (procInfo.hProcess != NULL)
{
CloseHandle(procInfo.hProcess);
}
if (procInfo.hThread != NULL)
{
CloseHandle(procInfo.hThread);
}
} }
- (void) interrupt - (void) interrupt
@ -935,11 +971,46 @@ GSCheckTasks()
} }
_hasTerminated = YES; _hasTerminated = YES;
TerminateProcess(proc_info.hProcess, 10); TerminateProcess(procInfo.hProcess, 10);
}
/*
* Wait for child process completion.
*/
static DWORD WINAPI _threadFunction(LPVOID t)
{
DWORD milliseconds = 60000;
int taskId = [(NSTask*)t processIdentifier];
for (;;)
{
NSConcreteWindowsTask *task;
[tasksLock lock];
task = (NSConcreteWindowsTask*)NSMapGet(activeTasks, (void*)taskId);
[tasksLock unlock];
if (t == nil)
{
return 0; // Task gone away.
}
switch (WaitForSingleObject(task->procInfo.hProcess, milliseconds))
{
case WAIT_OBJECT_0:
handleSignal(0); // Signal child process state change.
return 0;
case WAIT_TIMEOUT:
break; // Timeout ... retry
default:
return 0; // Error ... stop watching.
}
}
} }
- (void) launch - (void) launch
{ {
DWORD tid;
STARTUPINFO start_info; STARTUPINFO start_info;
NSString *lpath; NSString *lpath;
NSString *arg; NSString *arg;
@ -980,53 +1051,44 @@ GSCheckTasks()
NULL, /* env block */ NULL, /* env block */
[[self currentDirectoryPath] fileSystemRepresentation], [[self currentDirectoryPath] fileSystemRepresentation],
&start_info, &start_info,
&proc_info); &procInfo);
NSZoneFree(NSDefaultMallocZone(), c_args); NSZoneFree(NSDefaultMallocZone(), c_args);
if (result == 0) if (result == 0)
{ {
NSLog(@"Error launching task: %@", lpath); NSLog(@"Error launching task: %@", lpath);
return; return;
} }
_taskId = proc_info.dwProcessId;
_taskId = procInfo.dwProcessId;
_hasLaunched = YES; _hasLaunched = YES;
ASSIGN(_launchPath, lpath); // Actual path used. ASSIGN(_launchPath, lpath); // Actual path used.
[tasksLock lock]; [tasksLock lock];
NSMapInsert(activeTasks, (void*)_taskId, (void*)self); NSMapInsert(activeTasks, (void*)_taskId, (void*)self);
[tasksLock unlock]; [tasksLock unlock];
/*
* Create thread to watch for termination of process.
*/
wThread = CreateThread(NULL, 0, _threadFunction, (LPVOID)self, 0, &tid);
} }
- (void) _collectChild - (void) _collectChild
{ {
if (_hasCollected == NO) if (_hasCollected == NO)
{ {
/* FIXME: Implement */ DWORD eCode;
if (GetExitCodeProcess(procInfo.hProcess, &eCode) == 0)
{
NSLog(@"Error getting exit codef for process %d", _taskId);
}
else if (eCode != STILL_ACTIVE)
{
[self _terminatedChild: eCode];
}
} }
} }
- (int) terminationStatus
{
DWORD exit_code;
int result;
[super terminationStatus];
result = GetExitCodeProcess(proc_info.hProcess, &exit_code);
_terminationStatus = exit_code;
if (result == 0)
{
NSLog(@"Error getting exit code");
return -1;
}
return exit_code;
}
- (void) waitUntilExit
{
DWORD result;
result = WaitForSingleObject(proc_info.hProcess, INFINITE);
}
@end @end
#else /* !MINGW */ #else /* !MINGW */
@ -1339,7 +1401,7 @@ GSCheckTasks()
if (result < 0) if (result < 0)
{ {
NSLog(@"waitpid %d, result %d, error %s", NSLog(@"waitpid %d, result %d, error %s",
_taskId, result, GSLastErrorStr(errno)); _taskId, result, GSLastErrorStr(errno));
[self _terminatedChild: -1]; [self _terminatedChild: -1];
} }
else if (result == _taskId || (result > 0 && errno == 0)) else if (result == _taskId || (result > 0 && errno == 0))
@ -1348,7 +1410,7 @@ GSCheckTasks()
{ {
#ifdef WAITDEBUG #ifdef WAITDEBUG
NSLog(@"waitpid %d, termination status = %d", NSLog(@"waitpid %d, termination status = %d",
_taskId, _terminationStatus); _taskId, _terminationStatus);
#endif #endif
[self _terminatedChild: WEXITSTATUS(_terminationStatus)]; [self _terminatedChild: WEXITSTATUS(_terminationStatus)];
} }
@ -1356,20 +1418,24 @@ GSCheckTasks()
{ {
#ifdef WAITDEBUG #ifdef WAITDEBUG
NSLog(@"waitpid %d, termination status = %d", NSLog(@"waitpid %d, termination status = %d",
_taskId, _terminationStatus); _taskId, _terminationStatus);
#endif #endif
[self _terminatedChild: WTERMSIG(_terminationStatus)]; [self _terminatedChild: WTERMSIG(_terminationStatus)];
} }
#ifdef WAITDEBUG #ifdef WAITDEBUG
else else
NSLog(@"waitpid %d, event status = %d", {
_taskId, _terminationStatus); NSLog(@"waitpid %d, event status = %d",
_taskId, _terminationStatus);
}
#endif #endif
} }
#ifdef WAITDEBUG #ifdef WAITDEBUG
else else
NSLog(@"waitpid %d, result %d, error %s", {
_taskId, result, GSLastErrorStr(errno)); NSLog(@"waitpid %d, result %d, error %s",
_taskId, result, GSLastErrorStr(errno));
}
#endif #endif
} }
} }

View file

@ -29,14 +29,14 @@ main()
object: nil]; object: nil];
#ifdef __MINGW__ #ifdef __MINGW__
task = [NSTask launchedTaskWithLaunchPath: @"C:\\WINDOWS\\COMMAND\\MEM.EXE" task = [NSTask launchedTaskWithLaunchPath: @"C:\\windows\\system32\\mem.exe"
arguments: nil]; arguments: nil];
#else #else
task = [NSTask launchedTaskWithLaunchPath: @"/bin/ls" task = [NSTask launchedTaskWithLaunchPath: @"/bin/ls"
arguments: nil]; arguments: nil];
#endif #endif
[task waitUntilExit]; [task waitUntilExit];
printf("Exit status - %d\n", [task terminationStatus]); printf("Exit status - %d\n", [task terminationStatus]); fflush(stdout);
RELEASE(pool); RELEASE(pool);
pool = [NSAutoreleasePool new]; pool = [NSAutoreleasePool new];
@ -70,7 +70,7 @@ main()
{ {
NSAutoreleasePool *arp = [NSAutoreleasePool new]; NSAutoreleasePool *arp = [NSAutoreleasePool new];
[[NSRunLoop currentRunLoop] runOnceBeforeDate: [[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate:
[NSDate dateWithTimeIntervalSinceNow: 1]]; [NSDate dateWithTimeIntervalSinceNow: 1]];
RELEASE(arp); RELEASE(arp);
} }