try to make thread synchronisation I/O cleaner and perhaps safer if we do

something like run out of file descriptors for the pipe.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@38153 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2014-11-04 09:08:47 +00:00
parent 092d48d2f8
commit 18ef693dec
2 changed files with 36 additions and 7 deletions

View file

@ -1,3 +1,10 @@
2014-11-04 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSThread.m: When handling perform in another thread, check
more carefully for inter-thread communications (pipe on unix, event
on windows) and make sure we invalidate performers safely outside
the lock protected region when I/O is complete.
2014-11-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSHTTPURLHandle.m: Fix leak of handle when starting a new

View file

@ -897,12 +897,20 @@ static void *nsthreadLauncher(void* thread)
@implementation GSRunLoopThreadInfo
- (void) addPerformer: (id)performer
{
BOOL signalled = NO;
[lock lock];
[performers addObject: performer];
#if defined(__MINGW__)
if (SetEvent(event) == 0)
if (INVALID_HANDLE_VALUE != event)
{
NSLog(@"Set event failed - %@", [NSError _last]);
if (SetEvent(event) == 0)
{
NSLog(@"Set event failed - %@", [NSError _last]);
}
else
{
signalled = YES;
}
}
#else
/* The write could concievably fail if the pipe is full.
@ -911,19 +919,30 @@ static void *nsthreadLauncher(void* thread)
* and its runloop might stop during that ... so we need to check that
* outputFd is still valid.
*/
while (outputFd >= 0 && write(outputFd, "0", 1) != 1)
while (outputFd >= 0
&& NO == (signalled = (write(outputFd, "0", 1) == 1) ? YES : NO))
{
[lock unlock];
[lock lock];
}
#endif
if (YES == signalled)
{
[performers addObject: performer];
}
[lock unlock];
if (NO == signalled)
{
/* We failed to add the performer ... so we must invalidate it in
* case there is code waiting for it to complete.
*/
[performer invalidate];
}
}
- (void) dealloc
{
[self invalidate];
DESTROY(performers);
DESTROY(lock);
DESTROY(loop);
[super dealloc];
@ -990,9 +1009,11 @@ static void *nsthreadLauncher(void* thread)
- (void) invalidate
{
NSArray *p;
[lock lock];
[performers makeObjectsPerformSelector: @selector(invalidate)];
[performers removeAllObjects];
p = [performers autorelease];
performers = nil;
#ifdef __MINGW__
if (event != INVALID_HANDLE_VALUE)
{
@ -1012,6 +1033,7 @@ static void *nsthreadLauncher(void* thread)
}
#endif
[lock unlock];
[p makeObjectsPerformSelector: @selector(invalidate)];
}
- (void) fire