mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-31 16:50:58 +00:00
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:
parent
f53e056e90
commit
564eba5338
4 changed files with 116 additions and 46 deletions
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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]);
|
||||||
|
|
148
Source/NSTask.m
148
Source/NSTask.m
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue