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> 2014-11-01 Richard Frith-Macdonald <rfm@gnu.org>
* Source/GSHTTPURLHandle.m: Fix leak of handle when starting a new * Source/GSHTTPURLHandle.m: Fix leak of handle when starting a new

View file

@ -897,12 +897,20 @@ static void *nsthreadLauncher(void* thread)
@implementation GSRunLoopThreadInfo @implementation GSRunLoopThreadInfo
- (void) addPerformer: (id)performer - (void) addPerformer: (id)performer
{ {
BOOL signalled = NO;
[lock lock]; [lock lock];
[performers addObject: performer];
#if defined(__MINGW__) #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 #else
/* The write could concievably fail if the pipe is full. /* 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 * and its runloop might stop during that ... so we need to check that
* outputFd is still valid. * 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 unlock];
[lock lock]; [lock lock];
} }
#endif #endif
if (YES == signalled)
{
[performers addObject: performer];
}
[lock unlock]; [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 - (void) dealloc
{ {
[self invalidate]; [self invalidate];
DESTROY(performers);
DESTROY(lock); DESTROY(lock);
DESTROY(loop); DESTROY(loop);
[super dealloc]; [super dealloc];
@ -990,9 +1009,11 @@ static void *nsthreadLauncher(void* thread)
- (void) invalidate - (void) invalidate
{ {
NSArray *p;
[lock lock]; [lock lock];
[performers makeObjectsPerformSelector: @selector(invalidate)]; p = [performers autorelease];
[performers removeAllObjects]; performers = nil;
#ifdef __MINGW__ #ifdef __MINGW__
if (event != INVALID_HANDLE_VALUE) if (event != INVALID_HANDLE_VALUE)
{ {
@ -1012,6 +1033,7 @@ static void *nsthreadLauncher(void* thread)
} }
#endif #endif
[lock unlock]; [lock unlock];
[p makeObjectsPerformSelector: @selector(invalidate)];
} }
- (void) fire - (void) fire