# initng technical overview

initng is all about lauching and managing processes, daemons and services. The chief goals for this daemon are:

- Be able to lauch any daemon/service on demand.
- Only monitor and expose kernel fundamentals. Monitoring the System Configuration database or the notification namespace would be risky.
- No problematic out of band dependencies (they go stale and are often incorrect, as seen with today's SystemStarter).
- Unify lazy launch facilities to support complex daemon needs.

So what kind of reasons do we have to lauch stuff on demand? Well, for background, there is my rambling inventigation of what kind of daemons we have in the system.

So I think the fastest way to look at this is the number one way developers will interface with initng is the plist they'll use to describe a service/daemon to the system. With the exception of the "Program" variable and at least one "trigger" being specified, the rest of the values are optional:

>     <?xml version="1.0" encoding="UTF-8"?>
>     <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
>     <plist version="1.0">
>     <dict>
>     	<key>Program</key>
>     	<string></string>
>     	<key>ProgramArguments</key>
>     	<array/>
>     	<key>EnvironmentVariables</key>
>     	<dict/>
>     	<key>ServiceDescription</key>
>     	<string></string>
>     	<key>Disabled</key>
>     	<false/>
>     	<key>OnDemand</key>
>     	<true/>
>     	<key>LaunchOnce</key>
>     	<false/>
>     	<key>ServiceIPC</key>
>     	<false/>
>     	<key>UserName</key>
>     	<string></string>
>     	<key>GroupName</key>
>     	<string></string>
>     	<key>HardwareDevices</key>
>     	<dict/>
>     	<key>MachServiceNames</key>
>     	<array/>
>     	<key>WatchPaths</key>
>     	<array/>
>     	<key>Sockets</key>
>     	<array>
>     		<dict>
>     			<key>addrinfo_canonname</key>
>     			<false/>
>     			<key>addrinfo_family</key>
>     			<string></string>
>     			<key>addrinfo_nodename</key>
>     			<string></string>
>     			<key>addrinfo_numerichost</key>
>     			<false/>
>     			<key>addrinfo_passive</key>
>     			<false/>
>     			<key>addrinfo_protocol</key>
>     			<string></string>
>     			<key>addrinfo_servname</key>
>     			<string></string>
>     			<key>addrinfo_socktype</key>
>     			<string></string>
>     			<key>listen_depth</key>
>     			<integer>5</integer>
>     		</dict>
>     	</array>
>     	<key>SpecificTimeval</key>
>     	<integer>0</integer>
>     	<key>PeriodicSeconds</key>
>     	<integer>0</integer>
>     	<key>Cron</key>
>     	<dict>
>     		<key>DayOfTheMonth</key>
>     		<string></string>
>     		<key>DayOfTheWeek</key>
>     		<string></string>
>     		<key>Hour</key>
>     		<string></string>
>     		<key>Minute</key>
>     		<string></string>
>     		<key>Month</key>
>     		<string></string>
>     	</dict>
>     	<key>Limits</key>
>     	<dict>
>     		<key>CPUTime</key>
>     		<integer>0</integer>
>     		<key>CoreFileSize</key>
>     		<integer>0</integer>
>     		<key>DataSegSize</key>
>     		<integer>0</integer>
>     		<key>FileSize</key>
>     		<integer>0</integer>
>     		<key>MaxLockedMemory</key>
>     		<integer>0</integer>
>     		<key>MaxMemorySize</key>
>     		<integer>0</integer>
>     		<key>MaxUserProcesses</key>
>     		<integer>0</integer>
>     		<key>OpenFiles</key>
>     		<integer>0</integer>
>     		<key>PipeSize</key>
>     		<integer>0</integer>
>     		<key>StackSize</key>
>     		<integer>0</integer>
>     		<key>VirtualMemory</key>
>     		<integer>0</integer>
>     	</dict>
>     </dict>
>     </plist>

## So what do all these variables do?

Program | The path to the daemon/service/command.
ProgramArguments | An array of strings to pass as arguments to the program.
EnvironmentVariables | An array of extra environmental variables to pass to the program.
ServiceDescription | A description of what this service does.
Disabled | Is this service disabled?
OnDemand | Is this service capable of running on demand?
LauchOnce | Does this service need to be launched once (for whatever reason).
ServiceIPC | Does this service participate in the Service API? (Can we query it, ask it to shutdown, etc).
UserName | Who should this service run as?
GroupName | Which group should this service run as?
MachServiceNames | An array of services to publish into the mach namespace that this program is expected to service.
HardwareDevices | A dictionary of keys and values to watch for in the IOKit namespace, should they show up, launch this service (for blued, the USB printer team, etc).
WatchPaths | An array of strings that are file system paths to watch for change and then launch this job.
Sockets | An array of dictionaries that correspond to the addrinfo structure (see getaddrinfo(3)).
SpecificTimeval | Meant for any service that needs to be lauched at a specific time (see at(1) and batch(1)).
PeriodicSeconds | Meant for any true periodic job.
Cron | Support for crontab(5) style time specification.
Limits | Finally, since this is being lauched by pid 1, people want an easy way to specify limits.

## So given the above job/daemon/service description capabilities, what will the internals of initngd look like?

Fundamentally, a kqueue() and Libc plus system calls based state engine. Internally, we'll maintain two linked list, one of jobs that could run, and one of jobs that are running. We will use an IPC mechanism to accept binary job descriptions from tools that parse configuration files, be they the plist outlined above or legacy configuration files. This will simplify and insulate the daemon from failure. I don't see this as being very difficult. The only difficulty is just in the details and matters of risk/reward such as what API libraries we wish to use or not use and in defining how to effectively communicate to the daemon why they were launched (I still haven't found something I like yet, Mach has a solution for the Mach APIs, be we need something for the rest of the problem space.)

Eventually the IPC used to submit jobs will be public, but we can flush it out throughtout Merlot, we don't need to do it up front.

Long term work needs to be done on the IPC protocol between initng and the respective daemons for job control.

## So what has been done so far?

I've written a simple daemon that takes job requests from an external agent and launches them based on time related events. I just need to flush out the rest of the features and design now.

### Links:

My earlier daemon investigation.

Dave Zarzycki