views:

193

answers:

1

I'm using Distributed Objects in my application to provide communication between a tiny authentication agent program and the main application. The main application spawns NSTask's, which in turn will invoke the authentication program, which in turn will call back to the main program to get some user credentials. I know it sounds convoluted, but it has to work this way because of the way ssh gets passwords from a program in SSH_ASKPATH.

In my main application I have a single instance of an object called PasswordDialog, which I vend as follows;

PasswordDialog *vendedPasswordDialog=[[PasswordDialog alloc] init];  
[[NSConnection defaultConnection] setRootObject:vendedPasswordDialog];
[[NSConnection defaultConnection] registerName:@"MyConnectionName"]

This happens once when the application starts up.

In the authentication agent, I call back to this object as follows;

NSConnection *passwordDialogConnection = [NSConnection connectionWithRegisteredName:@"MyConnectionName" host:nil];

PasswordDialog *pdProxy = (PasswordDialog*)[passwordDialogConnection rootProxy];

NSString *responseStr = [pdProxy responseForPID:pidString host:hostnameString user:usernameString processInfo:[NSProcessInfo processInfo]];

The problem is that this doesn't work as I'd like. If there are multiple Authentication agents executing simultaneously I find that they can all access the same object and call the same method simultaneously. For example if I put a log statement at the beginning of "responseForPID" and at the end I get output like this;

beginMethod PID 3618848 on thread <NSThread: 0x30b050>{name = (null), num = 1} for object <PasswordDialog: 0x485460>
beginMethod PID 4882384 on thread <NSThread: 0x30b050>{name = (null), num = 1} for object <PasswordDialog: 0x485460>
beginMethod PID 4872848 on thread <NSThread: 0x30b050>{name = (null), num = 1} for object <PasswordDialog: 0x485460>

PID endMethod 4872848
PID endMethod 4882384
PID endMethod 3618848

Which seems like there are three different processes entering my method on the same thread on an object with the same address. Obviously I'm missing some fundamental understanding of Distributed Objects and threads here, but that seems like magic?

So eventually I get to my question(s)

(a) can someone explain what is going on here (ie how I can get log statements as above)

(b) Obviously I'm using Distributed objects incorrectly for my purpose. Can anyone suggest how I could do it correctly.

Thanks and thanks for reading to the end of this question!


Edit: Just to clarify. My "responseForPID" method looks something like this;

- (NSString*) responseForPID:(NSString*) pid host:(NSString*)hostname user:(NSString*) username processInfo:(NSProcessInfo*) info {

NSLog(@"beginMethod PID %@ on thread %@ for object %@",pid,[NSThread currentThread],self);

.... code to get the password 

NSLog(@"PID endMethod %@",pid);
return passwordString;

}
+1  A: 
beginMethod PID 3618848 on thread <NSThread: 0x30b050>{name = (null), num = 1} for object <PasswordDialog: 0x485460>
beginMethod PID 4882384 on thread <NSThread: 0x30b050>{name = (null), num = 1} for object <PasswordDialog: 0x485460>
beginMethod PID 4872848 on thread <NSThread: 0x30b050>{name = (null), num = 1} for object <PasswordDialog: 0x485460>

The PIDs are all different, indicating that the threads are executing in different processes.

So, no, there isn't simultaneous access to the method on a single thread. That the thread IDs are the same is likely coincidental; since the three processes are relatively simple and start up the same way, the threads happen to be allocated at the same address in each (or, more likely, the main thread is always at the same address by nature of app initialization).

Try printing [NSThread currentThread] when you spew those log lines and not just the string from the remote process.

bbum
Sorry I should have clarified. My Log statements are;NSLog(@"beginMethod PID %@ on thread %@ for object %@",pid,[NSThread currentThread],self)which is called inside the method "responseforPID". The PID's are the PIDs of the client processes which are passed as arguments to the "responseForPID" method. I had thought that "responseForPID" would passed as an NSInvocation from each of the clients to the server, and then the server would execute each NSInvocation instance in a synchronized manner?
Ira Cooke
It might seem like NSInvocations, but that isn't what goes across the wire. One issue with DO is that you can really confuse yourself quite easily. Namely, it is very easy to pass a proxy to an object over the wire without realizing it. Subsequent messages to the object on the foreign side will then go back across the wire. Sounds like that may be what is happening here.
bbum
Thanks very much for your answers. Yes, I think that is what's happened in my case. Actually, I should have seen this in the documentation: "If your application returns to the run loop or uses distributed objects either directly or indirectly, it can receive a remote message while it is already busy processing another". So in my case I changed my setup so I now only access proxy objects on the client side. I think I could also have used "setIndependentConversationQueueing:YES".
Ira Cooke