Author: rfm
Date: Tue Nov 4 10:08:47 2014
New Revision: 38153
URL: http://svn.gna.org/viewcvs/gnustep?rev=38153&view=rev
Log:
try to make thread synchronisation I/O cleaner and perhaps safer if we do
something like run out of file descriptors for the pipe.
Modified:
libs/base/trunk/ChangeLog
libs/base/trunk/Source/NSThread.m
Modified: libs/base/trunk/ChangeLog
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/ChangeLog?rev=38153&r1=38152&r2=38153&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog (original)
+++ libs/base/trunk/ChangeLog Tue Nov 4 10:08:47 2014
@@ -1,3 +1,10 @@
+2014-11-04 Richard Frith-Macdonald <[email protected]>
+
+ * 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 <[email protected]>
* Source/GSHTTPURLHandle.m: Fix leak of handle when starting a new
Modified: libs/base/trunk/Source/NSThread.m
URL:
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSThread.m?rev=38153&r1=38152&r2=38153&view=diff
==============================================================================
--- libs/base/trunk/Source/NSThread.m (original)
+++ libs/base/trunk/Source/NSThread.m Tue Nov 4 10:08:47 2014
@@ -897,12 +897,20 @@
@implementation GSRunLoopThreadInfo
- (void) addPerformer: (id)performer
{
+ BOOL signalled = NO;
+
[lock lock];
- [performers addObject: performer];
#if defined(__MINGW__)
- if (SetEvent(event) == 0)
- {
- NSLog(@"Set event failed - %@", [NSError _last]);
+ if (INVALID_HANDLE_VALUE != event)
+ {
+ 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 @@
* 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 @@
- (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 @@
}
#endif
[lock unlock];
+ [p makeObjectsPerformSelector: @selector(invalidate)];
}
- (void) fire
_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs