File: launchd.cpp

package info (click to toggle)
watchman 4.9.0-8
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 9,936 kB
  • sloc: cpp: 27,450; python: 6,534; java: 3,404; php: 3,257; ansic: 2,803; javascript: 1,116; makefile: 671; ruby: 364; sh: 124; xml: 102; lisp: 4
file content (68 lines) | stat: -rw-r--r-- 2,210 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
/* Copyright 2012-present Facebook, Inc.
 * Licensed under the Apache License, Version 2.0 */
#include "watchman.h"
#ifdef __APPLE__
#include <launch.h>

using watchman::FileDescriptor;

/* When running under launchd, we prefer to obtain our listening
 * socket from it.  We don't strictly need to run this way, but if we didn't,
 * when the user runs `watchman shutdown-server` the launchd job is left in
 * a waiting state and needs to be explicitly triggered to get it working
 * again.
 * By having the socket registered in our job description, launchd knows
 * that we want to be activated in this way and takes care of it for us.
 *
 * This is made more fun because Yosemite introduces launch_activate_socket()
 * as a shortcut for this flow and deprecated pretty much everything else
 * in launch.h.  We use the deprecated functions so that we can run on
 * older releases.
 * */
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
FileDescriptor w_get_listener_socket_from_launchd() {
  launch_data_t req, resp, socks;

  req = launch_data_new_string(LAUNCH_KEY_CHECKIN);
  if (req == NULL) {
    w_log(W_LOG_ERR, "unable to create LAUNCH_KEY_CHECKIN\n");
    return FileDescriptor();
  }

  resp = launch_msg(req);
  launch_data_free(req);

  if (resp == NULL) {
    w_log(W_LOG_ERR, "launchd checkin failed %s\n", strerror(errno));
    return FileDescriptor();
  }

  if (launch_data_get_type(resp) == LAUNCH_DATA_ERRNO) {
    w_log(W_LOG_ERR, "launchd checkin failed: %s\n",
          strerror(launch_data_get_errno(resp)));
    launch_data_free(resp);
    return FileDescriptor();
  }

  socks = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS);
  if (socks == NULL) {
    w_log(W_LOG_ERR, "launchd didn't provide any sockets\n");
    launch_data_free(resp);
    return FileDescriptor();
  }

  // the "sock" name here is coupled with the plist in main.c
  socks = launch_data_dict_lookup(socks, "sock");
  if (socks == NULL) {
    w_log(W_LOG_ERR, "launchd: \"sock\" wasn't present in Sockets\n");
    launch_data_free(resp);
    return FileDescriptor();
  }

  return FileDescriptor(
      launch_data_get_fd(launch_data_array_get_index(socks, 0)));
}
#endif

/* vim:ts=2:sw=2:et:
 */