Search code examples
objective-cmacosconnectionipcdistributed-objects

Testing Distributed Object Connections in OSX with Objective C


On Mac OSX with Objective C and Distributed Objects (IPC API), how can a server determine if the client has closed down their application and thus the NSConnection pointer has been broken? I mean, I might be in a while loop, reading a lot of data to send back from the server to the client, and I can test for stuff if I just knew what the trick was to determine if the client has suddenly disconnected.


Solution

  • Add this to your server's vended object class and then check it when doing something in any kind of loop for long periods of time. Replace "servicetest" phrase in the code below with the name of your actual process. You can run your client app and then check ps -ef at command line to see what your process is, if uncertain. It'll be the one with DerivedData if running temporarily in XCode.

    A little warning, though. This routine is kind of heavy and you shouldn't call it with every loop iteration. Instead, check like every 500 iterations of your while loop you might be in, for instance. You could also have a background timer that runs and checks. Or you could use rand to determine 1 in 5 odds and run it then.

    Note that this routine only runs properly with Distributed Objects on the same system, as in application to application IPC, rather than Distributed Objects over a LAN.

    So, when I detected that a client suddenly disconnected, I do a break on my while loop (where I was reading slow process data) and then did a pclose() on that process because there was no sense running it anymore.

    /* requires these includes
    #include <libproc.h>
    #include <sys/sysctl.h>
    #include <string>
    */
    
    - (bool)_clientSuddenlyDisconnected;
    {
    
      int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
        pid_t pids[1024];
        bzero(pids, 1024);
        proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
        for (int i = 0; i < numberOfProcesses; ++i) {
                if (pids[i] == 0) { continue; }
                char pathBuffer[PROC_PIDPATHINFO_MAXSIZE];
                bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
                proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer));
                if (strlen(pathBuffer) > 0) {
                        std::string sTest(pathBuffer);
                        sTest = "/" + sTest + "$$$";
                        if (sTest.find("/servicetest$$$") != std::string::npos) {
                            return false;
                        }
                }
        }
        return true;
    }