Re: Launchd daemon
Re: Launchd daemon
- Subject: Re: Launchd daemon
- From: Erwin Namal <email@hidden>
- Date: Mon, 29 Apr 2013 18:58:26 +0200
Your message didn't come to late. Thank you for sending it. The code was really useful.
I have taken part of it today to implement within my daemon. Now, I am looking for user app / daemon communication and will open a new thread for it.
Thanks for your help.
– E
On 24 mars 2013, at 05:26, Sidney San Martín <email@hidden> wrote:
> I just joined and saw this thread, might be able to fill in a couple of gaps (though as a result I don't have your email — hope you see this response).
>
>> - Communication will most probably be done with UNIX Domain Sockets.
>> - I will need to configure the plist, which is very well explained (in an other documentation).
>>
>> I have also taken a look at SampleD.
>> - It gets their socket from launch_data_dict_lookup(sockets_dict, "MyListenerSocket");
>> Do I need to obtain a control socket from launchd or can I register it myself using ctl_register()?
>
> UNIX domain sockets work great. You can even have launchd create the server end of it for you and grab it at checkin time.
>
> Here's some code from a project of mine that might help with this. Does it cover what you meant by "obtaining a control socket from launchd"? It also grabs a timeout — my daemon exits if it's been idle for a while, yours may not need to. (Replace log() with calls to asl_log() or your own helpful logging function):
>
> int launchdSocketFd = 0;
> int launchdTimeout = 0;
>
> launch_data_t checkin_request;
> launch_data_t checkin_response;
>
> // Check in with launchd. Even if we weren't launched by launchd these first two calls should succeed
> if ((checkin_request = launch_data_new_string(LAUNCH_KEY_CHECKIN)) == NULL) {
> log(ASL_LEVEL_ERR, @"launch_data_new_string(\"" LAUNCH_KEY_CHECKIN "\") Unable to create string.");
> exit(EXIT_FAILURE);
> }
> if ((checkin_response = launch_msg(checkin_request)) == NULL) {
> log(ASL_LEVEL_ERR, @"launch_msg(\"" LAUNCH_KEY_CHECKIN "\") IPC failure: %s", strerror(errno));
> exit(EXIT_FAILURE);
> }
>
> // If we were started by launchd, get the file descriptor of the socket launchd opened for us
> if (LAUNCH_DATA_DICTIONARY == launch_data_get_type(checkin_response)) {
> launch_data_t sockets_dict = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_SOCKETS);
> size_t socketCount;
> if (sockets_dict && (socketCount = launch_data_dict_get_count(sockets_dict))) {
> if(socketCount > 1){
> log(ASL_LEVEL_WARNING, @"Launchd gave us extra sockets, ignoring them");
> }
> launch_data_t listening_fd_array = launch_data_dict_lookup(sockets_dict, "sockserverSocket");
> if (listening_fd_array && launch_data_array_get_count(listening_fd_array)) {
> launchdSocketFd = launch_data_get_fd(launch_data_array_get_index(listening_fd_array, 0));
> }
> }
> launch_data_t timeout = launch_data_dict_lookup(checkin_response, LAUNCH_JOBKEY_TIMEOUT);
> if(timeout){
> launchdTimeout = launch_data_get_integer(timeout);
> }
> if(!launchdSocketFd){
> log(ASL_LEVEL_ERR, @"Missing a socket to answer requests!");
> exit(EXIT_FAILURE);
> }
> } else {
> errno = launch_data_get_errno(checkin_response);
> log(ASL_LEVEL_ERR, @"Couldn't check in with launchd: %m");
> }
> launch_data_free(checkin_request);
> launch_data_free(checkin_response);
>
>
>
>> - How to set up my project to use Objective-C for my daemon.
>> - What does my Objective-C entry point look like (int main(…) ?)
>> - How do I handle SIGKILL
>> - If I can't use a for/while/etc. loop, how do I prevent my daemon from exiting once the main function returns?
>> - Do I need to obtain a control socket from launchd or can I register it myself using ctl_register()?
>>
>>> Daemos are by definition command line.
>> Do you know how to select objective-C as developing language?
>
> Just create a Foundation command line tool! A launchd daemon can be *any* executable (though it shouldn't use AppKit), it isn't special. Your main()'ll probably look like this:
>
> int main () {
> [MyBigFancyController new];
> [[NSRunLoop currentRunLoop] run];
> return 0;
> }
>
> Do whatever initialization you want from main() — it can be inline, a call to a C function, or a call to one or more ObjC methods, as above. It can start listening to the domain socket you got from launchd — you're welcome to wrap it in an NSFileHandle and -acceptConnectionInBackgroundAndNotify — or open files, connect to other programs, whatever.
>
> The NSRunLoop is your infinite loop, the same one used by Cocoa apps, and the call to -run won't return while the it has input sources. Any evented ObjC call (NSTimer, -performSelector:afterDelay:, notification center, NSURLConnection, -acceptConnectionInBackgroundAndNotify, etc.) that can call you back at a later time registers itself with the run loop and counts as an input source, so don't worry about it.
> _______________________________________________
> Do not post admin requests to the list. They will be ignored.
> Darwin-dev mailing list (email@hidden)
> Help/Unsubscribe/Update your Subscription:
>
> This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden