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

Reply via email to