Calling CFRunLoop family on a Cocoa application - objective-c

I have a cocoa application in which I would like to use UNIX domain sockets to communicate with a system-wide daemon.
In a first step, my client will connect to the daemon and then listen for incoming log statements from the daemon.
The example I found, CFLocalServer from Apple, uses CFSockets to communicate between two command line utilities. I was able to set the daemon part of the code nicely, because I am free to decide what function to call in my daemon ([[NSRunLoop currentLoop] run] or CFRunLoopRun()). However, I have doubts about the client, which is a cocoa application.
In the code sample, the client first create them, connects, adds them as source to the current CFRunLoop for listening operations and then calls CFRunLoopRun(); until cancelled by CFRunLoopStop(CFRunLoopGetCurrent());
My question is: can I do all that inside a block on a serial dispatch queue created by an Objective-C cocoa application without interfering with the NSRunLoop in my application's main thread?

Yes, you can do that, although you may want to simply attach the socket to the main run loop and let it run normally (i.e. don't call CFRunLoopRun() since its already running).
I would also look at GCDAsyncSocket which is a very nice wrapper for all of this kind of work if your needs are complicated. It doesn't currently have support for unix domain sockets, but you can use jdiehl's socketUN branch which adds it.

Related

Running multiple instances of the same XPC service (NSXPCConnection)

Is it possible to run multiple instances of the same XPC service using the XPC APIs found in Foundation.framework (NSXPCConnection, etc.)? The docs don't provide much insight on this matter.
EDIT: Did a quick test, and it seems like only one instance of the service is running even though I created two XPC connections. Is there any way to have it run another instance?
A bit late, but the definitive answer to this question is provided in the xpcservice.plist manpage:
ServiceType (default: Application)
The type of the XPC Service specifies how the service is instantiated.
The values are:
• Application: Each application will have a unique instance of this service.
• User: There is one instance of the service process created for each user.
• System: There is one instance of the service process for the whole system. System XPC Services are restricted to reside in system frameworks and must be owned by root.
Bottom line: In most cases there is a single instance of an XPC Service and only in the case where different applications can connect to the same service (not even possible when the service is bundled with an app), will there be multiple instances (one-instance-per-app).
I believe XPC services designed for one instance per multiple connections. Probably, it is more convenient to manage named pipes with one running executable. So, the most likely it is impossible to create multiple instances simultaneously.
Since XPC services should have no state, it should not matter, whether one ore more instances are running:
XPC services are managed by launchd, which launches them on demand, restarts them if they crash, and terminates them (by sending SIGKILL) when they are idle. This is transparent to the application using the service, except for the case of a service that crashes while processing a message that requires a response. In that case, the application can see that its XPC connection has become invalid until the service is restarted by launchd. Because an XPC service can be terminated suddenly at any time, it must be designed to hold on to minimal state—ideally, your service should be completely stateless, although this is not always possible.
–– Creating XPC Services
Put all neccessary state information into the xpc call and deliver it back to the client, if it has to persist.
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man5/xpcservice.plist.5.html
ServiceType key in XPCService dictionary: Application or User or System
But this ‘ServiceType’ is irrelevant… IF Service is embedded in an application bundle then it will only be visible to the containing application and will be, by definition, Applicaton-type services. A subsequent connection request from an application to a service will result in a new connection to an existing service.
I know I'm late to the party, but while you can't do this with plain XPC,
there's library (a component of OpenEmu) that should be able to do what you're asking: OpenEmuXPCCommunicator

Twisted: spawn an application daemon from another application daemon

I have a Twisted application daemon which is started by twistd. This daemon acts as a daemon manager to manage many other Twisted application daemons. I can send the manager a "new" command via TCP and the manager should spawn(fork) another Twisted application daemon. My question is how can I do that? After fork, I think I should stop the manager's reactor loop, close opened file descriptors(logging file), then run the new Twisted application daemon. I want to know the details of how to do these things properly.
You should use the reactor's spawnProcess method. See http://twistedmatrix.com/documents/current/core/howto/process.html for details on its use.
You should not fork or do any of those other steps yourself. They are difficult to do correctly, and spawnProcess already does them for you.
If you're curious about how these things are done, you can browse the various implementations.

WCF Web Service with a Singleton COBOL VM

I have a WCF Web Service that has no concurrency configuration in the web.config, so I believe it is running as the default as persession. In the service, it uses a COBOL Virtual Machine to execute code that pulls data from COBOL Vision files. Per the developer of the COBOL VM, it is a singleton.
When more than one person accesses the service at a time, I'll get periodic crashes of the web service. What I believe is happening is that as one process is executing another separate process comes in at about the same time. The first process ends and closes the VM down through normal closing procedures. The second process is still executing and attempting to read/write data, but the VM was shutdown and it crashes. In the constructor for the web service, an instance of the VM is created and when a series of methods complete, the service is cleaned up and the VM closed out.
I have been reading up on Singleton concurrency in WCF web services and thinking I might need to switch to this instead. This way I can open the COBOL VM and keep it alive forever and eliminate my code shutting down the VM in my methods. The only data I need to share between requests is the status of the COBOL VM.
My alternative I'm thinking of is creating a server process that manages opening the VM and keeping it alive and allowing the web service to make read/write requests through that process instead.
Does this sound like the right path? I'm basically looking for a way to keep the Virtual Machine alive in a WCF web service situation and just keep executing code against it. The COBOL VM system sends me back locking information on the read/writes which I can use to handle retries or waits against.
Thanks,
Martin
The web service is now marked as:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single)]
From what I understand, this only allows a single thread to run through the web service at a time. Other requests are queued until the first completes. This was a quick fix that works in my situation because my web service doesn't require high concurrency. There are never more than a handful of requests coming in at a time.

IPC between server and many clients on Mac OS X

I have following scenario:
Server should be Daemon.
Other Apps should be clients.
Many clients should communicate with server to get their task done by server at a time.
These tasks are such as copyfile, deletefile etc.
My solution:
Server has 5 worker threads each containing named pipe. Each pipe's availability status is kept in Shared memory structure. When client wants to communicate with server, it checks which pipe is available from shared memory then opens that pipe & sends its message on that pipe, respective worker thread of server servers this client request. That worker thread sends request status (Success/failure) on that pipe so that client will become aware of last operation status.
As far as I know, pipes on Mac os x are unidirectional & they lack capability of creating unlimited instances like Windows.
What mechanism could be best suited for such kind of communication?
Thanks,
Vaibhav.
As far as I know, pipes on Mac os x are unidirectional & they lack capability of creating unlimited instances like Windows.
Pipes are one directional, but Unix sockets are not. This is probably what you are after if you want to directly port your code to OS X.
However, there are probably better ways to do what you want to do, including stuff like Distributed Objects which I admit I have never used. Even if you stick with a socket interface, I think one socket would be easier with a thread monitoring the socket and handing off work to worker threads as it arrives, using listen and accept. Better still, have an NSOperationQueue or a dispatch queue to put the work on, then the OS will handle the task of optimising the thread count.

How to find a locally available UDP port with unix Sockets API

I have an application where I have potentially many processes must send a message to one process. I figured the most expedient way to do this would be to just send a UDP datagram.
When opening a socket, I need to specify which port to listen to. As I just want to fire and forget the UDP datagram, I'd like to just have the OS pick an available port. I'd rather not have to hunt for one, especially as many instances of my process may be running. Is there a way I can tell the OS to just pick an available port (or better yet, not even open a listening socket) to fire and forget my UDP datagram?
Yes. Specify 0 as the port. The OS will pick an available port for you.
Answering the "Problem" rather than the "Question"
If all the processes are operating on the same PC, you might want to look into shared files or some other means of communications other than a networking stack.
I'd suggest you explore the options in Boost's Interprocess library
http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess.html
Quick guide here:
http://www.boost.org/doc/libs/1_37_0/doc/html/interprocess/quick_guide.html
Specifically, I suggest you use a named pipe or shared memory between your processes.