Module: Launch

Included in:
WEBrickHTTPServer
Defined in:
lib/launch.rb,
ext/launch/launch.c

Overview

Launch is a wrapper for the launch(3) API for daemons and agents spawned by launchd(8).

Launch agents and daemons MUST NOT:

  • Call daemon(3)

  • Do the equivalent of daemon(3) by calling fork and having the parent exit

Launch agents and daemons SHOULD NOT do the following as part of their starup initialization:

  • Set the user ID or group ID (Process::Sys.setuid, Process::Sys.setgid and friends)

  • Setup the working directory (Dir.chdir)

  • chroot(2)

  • setsid(2) (Process.setsid)

  • Close “stray” file descriptors

  • Change stdio(3) to /dev/null (STDOUT.reopen and friends)

  • Setup resource limits with setrusage (Process.setrlimit)

  • Ignore the SIGTERM signal (trap 'TERM', 'IGNORE')

The above is from launchd.plist(5). Please read it for further details.

To shut down cleanly trap 'TERM' and perform any shutdown steps before exiting.

Defined Under Namespace

Modules: JobKey, JobPolicy, Key, Socket Classes: Error, WEBrickHTTPServer

Constant Summary collapse

VERSION =

The version of launch you are using

'1.0'

Instance Method Summary collapse

Instance Method Details

#launch_checkinObject

Checks in with launch and retrieves the agent's configuration. The configuration can be retrieved later through <tt>@launch_checkin<tt>.


39
40
41
42
43
44
45
# File 'lib/launch.rb', line 39

def launch_checkin
  response = launch_message Launch::Key::CHECKIN

  return if response.nil?

  @launch_checkin = response
end

#launch_message(Launch: :Key::CHECKIN) ⇒ Object

launch_message wraps launch(3)'s launch_msg function. The argument is a message to send launchd from Launch::Key. Please use launch_checkin and launch_sockets instead of this method.

The response from launchd is converted to a ruby structure and freed (usually a Hash). Currently the following data types in the response are indistinguishable in the ruby structure:

  • STRING and OPAQUE

  • INTEGER, FD and ERRNO

Additionally, MACHPORT is ignored.

If there was a failure to retrieve checkin data an error will be raised.


96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'ext/launch/launch.c', line 96

static VALUE
message(VALUE self, VALUE message) {
  VALUE out, tmp;
  launch_data_t send, response;
  launch_data_type_t response_type;

  message = rb_str_to_str(message);

  send = launch_data_new_string(StringValueCStr(message));

  if (send == NULL) {
    tmp = rb_inspect(message);
    rb_raise(cLaunchError, "unable to create message %s",
        StringValueCStr(tmp));
  }

  response = launch_msg(send);

  if (response == NULL)
    rb_sys_fail("launch_msg");

  response_type = launch_data_get_type(response);

  if (response_type == LAUNCH_DATA_ERRNO) {
    errno = launch_data_get_errno(response);
    rb_sys_fail("launch_msg");
  }

  out = launch_data_to_ruby(response);

  launch_data_free(response);

  return out;
}

#launch_sockets(name, socket_class) ⇒ Object

Creates ruby sockets from the sockets list in name. socket_class.for_fd is called for each socket in the named list.

name comes from the socket's name key in the launchd plist.

Example plist Sockets dictionary:

<key>Sockets</key>
<dict>
  <key>EchoSocket</key>
  <dict>
    <key>SockServiceName</key>
    <string>12345</string>
  </dict>
</dict>

Example call:

servers = launch_sockets 'Echo', TCPServer

p servers.map { |server| server.addr }

Raises:


70
71
72
73
74
75
76
77
78
79
80
# File 'lib/launch.rb', line 70

def launch_sockets name, socket_class
  require 'socket'

  sockets = @launch_checkin[Launch::JobKey::SOCKETS][name]

  raise Error, "no sockets found for #{name.inspect}" unless sockets

  sockets.map do |fd|
    socket_class.for_fd fd
  end
end