error handling for distributed object

Discussion in 'Mac Programming' started by Howiieque, May 1, 2009.

  1. Howiieque macrumors regular

    Joined:
    Feb 1, 2009
    #1
    HI. I made an experiment about distributed object.

    This exception handling is from a book:
    Code:
    /*- (void)connectionDidDie:(NSNotification *)aNotification
    {
    	NSConnection *deadConnection = [aNotification object];
    	int i;
    	for(i = [listOfClients count] - 1; i >= 0; i--)
    	{
    		id    currentClient = [listOfClients objectAtIndex:i];
    		
    		NS_DURING
    		if([currentClient respondsToSelector:@selector(connectionForProxy)])
    		{
    			if(deadConnection == [currentClient connectionForProxy])
    			{
    				[listOfClients removeObjectAtIndex:i];
    				NSLog(@"Removed client from client list.");
    			}
    		}
    		NS_HANDLER
    		[listOfClients removeObjectAtIndex:i];
    		NSLog(@"Removed client from client list.");
    		NS_ENDHANDLER
    	}
    }*/
    I want to change it to use the for in loop.

    Code:
    - (void)connectionDidDie:(NSNotification *)aNotification {
    	NSConnection *deadConnection=[aNotification object];
    	for(id currentClient in listOfClients) {
    		@try {
    			if([currentClient respondsToSelector:@selector(connectionForProxy)]) {
    				if([currentClient connectionForProxy]==deadConnection) {
    					[listOfClients removeObject:currentClient];
    					NSLog(@"Removed dead client: %@.", currentClient);
    				}
    			}
    		}
    		@catch (NSException * e) {
    			int i=[listOfClients indexOfObject:currentClient];
    			[listOfClients removeObjectAtIndex:i];
    			//[listOfClients removeObject:currentClient];
    			NSLog(@"%@. Removed dead client %@.", [e reason], currentClient);
    		}
    		@finally {
    		}
    	}
    }
    But [listOfClients removeObject:currentClient]; leads to an error. I can't figure it out. I tried to split it into two steps, but still had problems.

    Another question is that [currentClient respondsToSelector:mad:selector(connectionForProxy)] never return YES. But it should. Testing it in gdb, I explicitly sent the message and it actually respond to connectionForProxy. Could someone give me an explanation?

    I explicitly make it don't remove itself from the server list in AEClient.m , for the test of the block above.
    Here's the whole codes:
     

    Attached Files:

  2. Guiyon macrumors 6502a

    Joined:
    Mar 19, 2008
    Location:
    North Shore, MA
    #2
    When using fast enumeration you are not allowed to modify the array you are enumerating over. Attempts to modify the source object will result in an exception being thrown. I'd suggest downloading Apple's "The Objective-C 2.0 Programming Language" PDF and looking over the chapter on FE, there are few useful tips/gotchas in there.
     
  3. Howiieque thread starter macrumors regular

    Joined:
    Feb 1, 2009
    #3
    Thank you for your hint which to the point.
    But why in the if test, it doesn't respond to connectionForProxy? I still haven't a clue.
     
  4. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #4
    Most likely respondsToSelector: is being sent to the actual client object, not the NSDistantObject.
     
  5. Catfish_Man macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #5
    fwiw this isn't a new requirement; the new part is that it's enforced properly. Previously it was enforced by occasionally failing in mysterious ways.
     
  6. Howiieque thread starter macrumors regular

    Joined:
    Feb 1, 2009
    #6
    Thanks for your reply, kainjow.
    But I still don't quite understand. In the gdb, I typed print-object [currentClient connectionForProxy], and it returned(displayed) a connection object.
    Although the author didn't give a lot of details about this code block, I think in this way it can handle the error. Or else the programme will never execute the inner if test.
    Did the mechanism changed as time went by, or this example can't work properly? Is there some suggestion to fix it?
    Could you give a little more explanation.
     
  7. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #7
    I guess the real question is, when will currentClient not respond to that selector when it's a valid object?
     
  8. Howiieque thread starter macrumors regular

    Joined:
    Feb 1, 2009
    #8
    In general, it might work. But I still have some bugs can't track down.
    1.
    Code:
    for (int i=[listOfClients count]-1; i>=0; i--) {
    		id currentClient=[listOfClients objectAtIndex:i];
    		@try {
    			if([currentClient respondsToSelector:@selector(connectionForProxy)]) {
    				if([currentClient connectionForProxy]==deadConnection) {
    					[listOfClients removeObjectAtIndex:i];
    					NSLog(@"Removed dead client.");
    				}
    			}
    		}
    		@catch (NSException * e) {
    			[listOfClients removeObjectAtIndex:i];
    			NSLog(@"error: %@. Removed dead client.", [e reason]);
    		}
    	}
    case one. Connection works well. RespondsToSelector: is to be sent to the actual object, and NO returned.
    case two. Connection is broken. Exception raises.
    inner if has no chance to executes.

    I have changed it to use NSSocketPort.
    1. I launched one client, and then forced it exit.( maybe the [server removeMessageClient:self] was not invoked) In the terminal, it didn't show client was removed. Obviously, it can't handle the error. It seems that the connection was broken, and no notification was post.
    2. Then I launched some more clients, and let them quit properly.( without the server relaunching) In this situation, it also failed to remove clients.
    latest codes:
     

    Attached Files:

Share This Page