mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-17 11:11:46 +00:00
fixups for win32 pipe management
git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28747 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
739422c5aa
commit
30f0a67889
8 changed files with 190 additions and 84 deletions
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2009-09-27 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
|
* Source\win32\GSFileHandle.m:
|
||||||
|
* Source\win32\NSMessagePort.m:
|
||||||
|
* Source\win32\GSRunLoopCtxt.m:
|
||||||
|
* Source\win32\NSStream.m:
|
||||||
|
* Source\win32\NSMessagePortNameServer.m:
|
||||||
|
* Source\NSPipe.m:
|
||||||
|
* Source\NSTask.m:
|
||||||
|
Fixes to try and improve subtask handling on windows.
|
||||||
|
1. change scheme to create all handles as not inheritable, and
|
||||||
|
just make the handles we want the child to have inheritable while
|
||||||
|
we are launching the child.
|
||||||
|
2. peek the data on pipes and refrain from notifying about data
|
||||||
|
availability if the pipe doesn't really have data. This is horrid and
|
||||||
|
means we poll pipes ... but I can see no other way of implementing the
|
||||||
|
api on windows as I can find no way to get windows to tell use when
|
||||||
|
data is available.
|
||||||
|
|
||||||
2009-09-23 Richard Frith-Macdonald <rfm@gnu.org>
|
2009-09-23 Richard Frith-Macdonald <rfm@gnu.org>
|
||||||
|
|
||||||
* Source/NSURL.m: OSX compatibility tweaks ... allows initialisation
|
* Source/NSURL.m: OSX compatibility tweaks ... allows initialisation
|
||||||
|
|
|
@ -87,7 +87,7 @@
|
||||||
HANDLE readh, writeh;
|
HANDLE readh, writeh;
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
saAttr.bInheritHandle = TRUE;
|
saAttr.bInheritHandle = FALSE;
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
if (CreatePipe(&readh, &writeh, &saAttr, 0) != 0)
|
if (CreatePipe(&readh, &writeh, &saAttr, 0) != 0)
|
||||||
|
|
|
@ -1092,6 +1092,10 @@ quotedFromString(NSString *aString)
|
||||||
NSDictionary *env;
|
NSDictionary *env;
|
||||||
NSMutableArray *toClose;
|
NSMutableArray *toClose;
|
||||||
NSFileHandle *hdl;
|
NSFileHandle *hdl;
|
||||||
|
HANDLE hIn;
|
||||||
|
HANDLE hOut;
|
||||||
|
HANDLE hErr;
|
||||||
|
id last = nil;
|
||||||
|
|
||||||
if (_hasLaunched)
|
if (_hasLaunched)
|
||||||
{
|
{
|
||||||
|
@ -1163,6 +1167,13 @@ quotedFromString(NSString *aString)
|
||||||
start_info.dwFlags |= STARTF_USESTDHANDLES;
|
start_info.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
|
||||||
toClose = [NSMutableArray arrayWithCapacity: 3];
|
toClose = [NSMutableArray arrayWithCapacity: 3];
|
||||||
|
|
||||||
|
if (_standardInput == nil)
|
||||||
|
{
|
||||||
|
start_info.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
hdl = [self standardInput];
|
hdl = [self standardInput];
|
||||||
if ([hdl isKindOfClass: [NSPipe class]])
|
if ([hdl isKindOfClass: [NSPipe class]])
|
||||||
{
|
{
|
||||||
|
@ -1170,7 +1181,15 @@ quotedFromString(NSString *aString)
|
||||||
[toClose addObject: hdl];
|
[toClose addObject: hdl];
|
||||||
}
|
}
|
||||||
start_info.hStdInput = [hdl nativeHandle];
|
start_info.hStdInput = [hdl nativeHandle];
|
||||||
|
}
|
||||||
|
hIn = start_info.hStdInput;
|
||||||
|
|
||||||
|
if (_standardOutput == nil)
|
||||||
|
{
|
||||||
|
start_info.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
hdl = [self standardOutput];
|
hdl = [self standardOutput];
|
||||||
if ([hdl isKindOfClass: [NSPipe class]])
|
if ([hdl isKindOfClass: [NSPipe class]])
|
||||||
{
|
{
|
||||||
|
@ -1178,7 +1197,15 @@ quotedFromString(NSString *aString)
|
||||||
[toClose addObject: hdl];
|
[toClose addObject: hdl];
|
||||||
}
|
}
|
||||||
start_info.hStdOutput = [hdl nativeHandle];
|
start_info.hStdOutput = [hdl nativeHandle];
|
||||||
|
}
|
||||||
|
hOut = start_info.hStdOutput;
|
||||||
|
|
||||||
|
if (_standardError == nil)
|
||||||
|
{
|
||||||
|
start_info.hStdError = GetStdHandle(STD_ERROR_HANDLE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
hdl = [self standardError];
|
hdl = [self standardError];
|
||||||
if ([hdl isKindOfClass: [NSPipe class]])
|
if ([hdl isKindOfClass: [NSPipe class]])
|
||||||
{
|
{
|
||||||
|
@ -1192,22 +1219,48 @@ quotedFromString(NSString *aString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
start_info.hStdError = [hdl nativeHandle];
|
start_info.hStdError = [hdl nativeHandle];
|
||||||
|
}
|
||||||
|
hErr = start_info.hStdError;
|
||||||
|
|
||||||
|
/* Make the handles inheritable only temporarily while launching the
|
||||||
|
* child task. This section must be lock protected so we don't have
|
||||||
|
* another thread trying to launch at the same time and get handles
|
||||||
|
* inherited by the wrong threads.
|
||||||
|
*/
|
||||||
|
[tasksLock lock];
|
||||||
|
SetHandleInformation(hIn, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||||
|
SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||||
|
SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
|
||||||
|
|
||||||
result = CreateProcessW(wexecutable,
|
result = CreateProcessW(wexecutable,
|
||||||
w_args,
|
w_args,
|
||||||
NULL, /* proc attrs */
|
NULL, /* proc attrs */
|
||||||
NULL, /* thread attrs */
|
NULL, /* thread attrs */
|
||||||
1, /* inherit handles */
|
1, /* inherit handles */
|
||||||
// CREATE_NO_WINDOW|DETACHED_PROCESS|CREATE_UNICODE_ENVIRONMENT,
|
0
|
||||||
CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT,
|
// |CREATE_NO_WINDOW
|
||||||
|
/* One would have thought the the CREATE_NO_WINDOW flag should be used,
|
||||||
|
* but apparently this breaks for old 16bit applications/tools on XP.
|
||||||
|
*/
|
||||||
|
|DETACHED_PROCESS
|
||||||
|
|CREATE_UNICODE_ENVIRONMENT,
|
||||||
envp, /* env block */
|
envp, /* env block */
|
||||||
(const unichar*)[[self currentDirectoryPath] fileSystemRepresentation],
|
(const unichar*)[[self currentDirectoryPath] fileSystemRepresentation],
|
||||||
&start_info,
|
&start_info,
|
||||||
&procInfo);
|
&procInfo);
|
||||||
NSZoneFree(NSDefaultMallocZone(), w_args);
|
|
||||||
if (result == 0)
|
if (result == 0)
|
||||||
{
|
{
|
||||||
NSLog(@"Error launching task: %@", lpath);
|
last = [NSError _last];
|
||||||
|
}
|
||||||
|
NSZoneFree(NSDefaultMallocZone(), w_args);
|
||||||
|
SetHandleInformation(hIn, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
SetHandleInformation(hOut, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
SetHandleInformation(hErr, HANDLE_FLAG_INHERIT, 0);
|
||||||
|
[tasksLock unlock];
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
{
|
||||||
|
NSLog(@"Error launching task: %@ ... %@", lpath, last);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2003,7 +2003,37 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
||||||
}
|
}
|
||||||
[self postReadNotification];
|
[self postReadNotification];
|
||||||
}
|
}
|
||||||
else if (operation == NSFileHandleDataAvailableNotification)
|
else
|
||||||
|
{
|
||||||
|
/* If this is not a socket or a standard file, we assume it's a pipe
|
||||||
|
* and therefore we need to check to see if data really is available.
|
||||||
|
*/
|
||||||
|
if (NO == isSocket && NO == isStandardFile)
|
||||||
|
{
|
||||||
|
HANDLE h = (HANDLE)_get_osfhandle(descriptor);
|
||||||
|
DWORD bytes = 0;
|
||||||
|
|
||||||
|
if (PeekNamedPipe(h, 0, 0, 0, &bytes, 0) == 0)
|
||||||
|
{
|
||||||
|
DWORD e = GetLastError();
|
||||||
|
|
||||||
|
if (e != ERROR_BROKEN_PIPE && e != ERROR_HANDLE_EOF)
|
||||||
|
{
|
||||||
|
NSLog(@"pipe peek problem %d, %@", e, [NSError _last]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
/* In the case of a broken pipe, we fall through so that a read
|
||||||
|
* attempt is performed allowing higer level code to notice the
|
||||||
|
* problem and deal with it.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else if (bytes == 0)
|
||||||
|
{
|
||||||
|
return; // No data available yet.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation == NSFileHandleDataAvailableNotification)
|
||||||
{
|
{
|
||||||
[self postReadNotification];
|
[self postReadNotification];
|
||||||
}
|
}
|
||||||
|
@ -2068,6 +2098,7 @@ NSString * const GSSOCKSRecvAddr = @"GSSOCKSRecvAddr";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) receivedEventWrite
|
- (void) receivedEventWrite
|
||||||
|
|
|
@ -486,6 +486,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
||||||
watcher = (GSRunLoopWatcher*)GSIArrayItemAtIndex(_trigger, count).obj;
|
watcher = (GSRunLoopWatcher*)GSIArrayItemAtIndex(_trigger, count).obj;
|
||||||
if (watcher->_invalidated == NO)
|
if (watcher->_invalidated == NO)
|
||||||
{
|
{
|
||||||
|
NSDebugMLLog(@"NSRunLoop", @"trigger watcher %@", watcher);
|
||||||
i = [contexts count];
|
i = [contexts count];
|
||||||
while (i-- > 0)
|
while (i-- > 0)
|
||||||
{
|
{
|
||||||
|
@ -511,6 +512,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
||||||
// if there are windows message
|
// if there are windows message
|
||||||
if (wait_return == WAIT_OBJECT_0 + num_handles)
|
if (wait_return == WAIT_OBJECT_0 + num_handles)
|
||||||
{
|
{
|
||||||
|
NSDebugMLLog(@"NSRunLoop", @"processing windows messages");
|
||||||
[self processAllWindowsMessages: num_winMsgs within: contexts];
|
[self processAllWindowsMessages: num_winMsgs within: contexts];
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
@ -518,6 +520,7 @@ static const NSMapTableValueCallBacks WatcherMapValueCallBacks =
|
||||||
// if there aren't events
|
// if there aren't events
|
||||||
if (wait_return == WAIT_TIMEOUT)
|
if (wait_return == WAIT_TIMEOUT)
|
||||||
{
|
{
|
||||||
|
NSDebugMLLog(@"NSRunLoop", @"timeout without events");
|
||||||
completed = YES;
|
completed = YES;
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,7 +194,7 @@ static Class messagePortClass = 0;
|
||||||
|
|
||||||
security.nLength = sizeof(SECURITY_ATTRIBUTES);
|
security.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
security.lpSecurityDescriptor = 0; // Default
|
security.lpSecurityDescriptor = 0; // Default
|
||||||
security.bInheritHandle = TRUE;
|
security.bInheritHandle = FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ static void clean_up_names(void)
|
||||||
|
|
||||||
security.nLength = sizeof(SECURITY_ATTRIBUTES);
|
security.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
security.lpSecurityDescriptor = 0; // Default
|
security.lpSecurityDescriptor = 0; // Default
|
||||||
security.bInheritHandle = TRUE;
|
security.bInheritHandle = FALSE;
|
||||||
|
|
||||||
registry = @"Software\\GNUstepNSMessagePort";
|
registry = @"Software\\GNUstepNSMessagePort";
|
||||||
rc = RegCreateKeyExW(
|
rc = RegCreateKeyExW(
|
||||||
|
|
|
@ -1016,7 +1016,7 @@
|
||||||
fileSystemRepresentation];
|
fileSystemRepresentation];
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
saAttr.bInheritHandle = TRUE;
|
saAttr.bInheritHandle = FALSE;
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
handle = CreateFileW(name,
|
handle = CreateFileW(name,
|
||||||
|
@ -1067,7 +1067,7 @@ done:
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
saAttr.bInheritHandle = TRUE;
|
saAttr.bInheritHandle = FALSE;
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1346,7 +1346,7 @@ done:
|
||||||
NSAssert(handle == INVALID_HANDLE_VALUE, NSInternalInconsistencyException);
|
NSAssert(handle == INVALID_HANDLE_VALUE, NSInternalInconsistencyException);
|
||||||
|
|
||||||
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
saAttr.bInheritHandle = TRUE;
|
saAttr.bInheritHandle = FALSE;
|
||||||
saAttr.lpSecurityDescriptor = NULL;
|
saAttr.lpSecurityDescriptor = NULL;
|
||||||
|
|
||||||
handle = CreateNamedPipeW([path fileSystemRepresentation],
|
handle = CreateNamedPipeW([path fileSystemRepresentation],
|
||||||
|
|
Loading…
Reference in a new issue