Author: rfm
Date: Thu Apr  2 17:59:48 2015
New Revision: 38448

URL: http://svn.gna.org/viewcvs/gnustep?rev=38448&view=rev
Log:
Try to better handle exception in method in another thread

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=38448&r1=38447&r2=38448&view=diff
==============================================================================
--- libs/base/trunk/ChangeLog   (original)
+++ libs/base/trunk/ChangeLog   Thu Apr  2 17:59:48 2015
@@ -1,3 +1,9 @@
+2015-04-02  Richard Frith-Macdonald <[email protected]>
+
+       * Source/NSThread.m: If an exception occurs while performing a
+       selector in another thread, catch it and cleanup (and if the
+       caller is waiting, pass the exception back to it).
+
 2015-04-01  Wolfgang Lux  <[email protected]>
 
        * configure.ac: Fix comment syntax and use standard operator in

Modified: libs/base/trunk/Source/NSThread.m
URL: 
http://svn.gna.org/viewcvs/gnustep/libs/base/trunk/Source/NSThread.m?rev=38448&r1=38447&r2=38448&view=diff
==============================================================================
--- libs/base/trunk/Source/NSThread.m   (original)
+++ libs/base/trunk/Source/NSThread.m   Thu Apr  2 17:59:48 2015
@@ -222,6 +222,8 @@
   NSConditionLock      *lock;          // Not retained.
   NSArray              *modes;
   BOOL                  invalidated;
+@public
+  NSException           *exception;
 }
 + (GSPerformHolder*) newForReceiver: (id)r
                           argument: (id)a
@@ -1286,6 +1288,7 @@
 
 - (void) dealloc
 {
+  DESTROY(exception);
   DESTROY(receiver);
   DESTROY(argument);
   DESTROY(modes);
@@ -1309,7 +1312,23 @@
     }
   threadInfo = GSRunLoopInfoForThread(GSCurrentThread());
   [threadInfo->loop cancelPerformSelectorsWithTarget: self];
-  [receiver performSelector: selector withObject: argument];
+  NS_DURING
+    {
+      [receiver performSelector: selector withObject: argument];
+    }
+  NS_HANDLER
+    {
+      ASSIGN(exception, localException);
+      if (nil == lock)
+        {
+          NSLog(@"*** NSRunLoop ignoring exception '%@' (reason '%@') "
+            @"raised during perform in other thread... with receiver %p "
+            @"and selector '%@'",
+            [localException name], [localException reason], receiver,
+            NSStringFromSelector(selector));
+        }
+    }
+  NS_ENDHANDLER
   DESTROY(receiver);
   DESTROY(argument);
   DESTROY(modes);
@@ -1452,9 +1471,19 @@
          RELEASE(l);
           if ([h isInvalidated] == YES)
             {
+              RELEASE(h);
               [NSException raise: NSInternalInconsistencyException
                           format: @"perform on finished thread"];
+            }
+          /* If we have an exception passed back from the remote thread,
+           * re-raise it.
+           */
+          if (nil != h->exception)
+            {
+              NSException       *e = AUTORELEASE(RETAIN(h->exception));
+
               RELEASE(h);
+              [e raise];
             }
        }
       RELEASE(h);


_______________________________________________
Gnustep-cvs mailing list
[email protected]
https://mail.gna.org/listinfo/gnustep-cvs

Reply via email to