[launchd-changes] [22850] trunk/launchd/src

source_changes at macosforge.org source_changes at macosforge.org
Mon Sep 11 14:08:30 PDT 2006


Revision: 22850
Author:   zarzycki at apple.com
Date:     2006-09-11 14:08:28 -0700 (Mon, 11 Sep 2006)

Log Message:
-----------
Consolidate OS runtime support into a file to ease porting.

Modified Paths:
--------------
    trunk/launchd/src/Makefile.am
    trunk/launchd/src/Makefile.in
    trunk/launchd/src/init.c
    trunk/launchd/src/launchd.c
    trunk/launchd/src/launchd.h
    trunk/launchd/src/launchd_core_logic.c
    trunk/launchd/src/launchd_mach_ipc.c
    trunk/launchd/src/launchd_unix_ipc.c

Added Paths:
-----------
    trunk/launchd/src/launchd_runtime.c
    trunk/launchd/src/launchd_runtime.h

Modified: trunk/launchd/src/Makefile.am
===================================================================
--- trunk/launchd/src/Makefile.am	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/Makefile.am	2006-09-11 21:08:28 UTC (rev 22850)
@@ -41,11 +41,12 @@
 
 launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -Wno-unused-parameter -fvisibility=hidden
 launchd_LDFLAGS = -lbsm
-launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c launchd_mach_ipc.c init.c bootstrapServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c mpm_replyUser.c
+launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c launchd_mach_ipc.c init.c bootstrapServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c mpm_replyUser.c launchd_runtime.c
 
-launchd_mach_ipc.c:: bootstrap.h bootstrapServer.h notifyServer.h launchd_internal.h
+launchd_runtime.c:: notifyServer.h launchd_internal.h
+launchd_mach_ipc.c:: bootstrap.h bootstrapServer.h
 launchd_core_logic.c:: bootstrap.h mpm_reply.h
-launchd.c:: bootstrap.h launchd_internalServer.h launchd_internal.h notifyServer.h bootstrapServer.h
+#launchd.c:: bootstrap.h launchd_internalServer.h launchd_internal.h notifyServer.h bootstrapServer.h
 
 launchproxy_LDFLAGS = -weak_framework Security
 

Modified: trunk/launchd/src/Makefile.in
===================================================================
--- trunk/launchd/src/Makefile.in	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/Makefile.in	2006-09-11 21:08:28 UTC (rev 22850)
@@ -88,7 +88,7 @@
 am__launchd_SOURCES_DIST = launchd.c launchd_core_logic.c \
 	launchd_unix_ipc.c launchd_mach_ipc.c init.c bootstrapServer.c \
 	notifyServer.c launchd_internalUser.c launchd_internalServer.c \
-	mpm_replyUser.c
+	mpm_replyUser.c launchd_runtime.c
 @LIBS_ONLY_FALSE at am_launchd_OBJECTS = launchd-launchd.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_core_logic.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_unix_ipc.$(OBJEXT) \
@@ -98,7 +98,8 @@
 @LIBS_ONLY_FALSE@	launchd-notifyServer.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_internalUser.$(OBJEXT) \
 @LIBS_ONLY_FALSE@	launchd-launchd_internalServer.$(OBJEXT) \
- at LIBS_ONLY_FALSE@	launchd-mpm_replyUser.$(OBJEXT)
+ at LIBS_ONLY_FALSE@	launchd-mpm_replyUser.$(OBJEXT) \
+ at LIBS_ONLY_FALSE@	launchd-launchd_runtime.$(OBJEXT)
 launchd_OBJECTS = $(am_launchd_OBJECTS)
 launchd_LDADD = $(LDADD)
 launchproxy_SOURCES = launchproxy.c
@@ -236,7 +237,8 @@
 @LIBS_ONLY_FALSE at SystemStarter_SOURCES = StartupItems.c IPC.c SystemStarter.c
 @LIBS_ONLY_FALSE at launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -Wno-unused-parameter -fvisibility=hidden
 @LIBS_ONLY_FALSE at launchd_LDFLAGS = -lbsm
- at LIBS_ONLY_FALSE@launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c launchd_mach_ipc.c init.c bootstrapServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c mpm_replyUser.c
+ at LIBS_ONLY_FALSE@launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c launchd_mach_ipc.c init.c bootstrapServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c mpm_replyUser.c launchd_runtime.c
+#launchd.c:: bootstrap.h launchd_internalServer.h launchd_internal.h notifyServer.h bootstrapServer.h
 @LIBS_ONLY_FALSE at launchproxy_LDFLAGS = -weak_framework Security
 @LIBS_ONLY_FALSE at man1_MANS = wait4path.1 launchctl.1
 @LIBS_ONLY_FALSE at man5_MANS = launchd.plist.5 launchd.conf.5
@@ -426,6 +428,7 @@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd_internalServer.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd_internalUser.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd_mach_ipc.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd_runtime.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-launchd_unix_ipc.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-mpm_replyUser.Po at am__quote@
 @AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/launchd-notifyServer.Po at am__quote@
@@ -672,6 +675,20 @@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	source='mpm_replyUser.c' object='launchd-mpm_replyUser.obj' libtool=no @AMDEPBACKSLASH@
 @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
 @am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -c -o launchd-mpm_replyUser.obj `if test -f 'mpm_replyUser.c'; then $(CYGPATH_W) 'mpm_replyUser.c'; else $(CYGPATH_W) '$(srcdir)/mpm_replyUser.c'; fi`
+
+launchd-launchd_runtime.o: launchd_runtime.c
+ at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -MT launchd-launchd_runtime.o -MD -MP -MF "$(DEPDIR)/launchd-launchd_runtime.Tpo" -c -o launchd-launchd_runtime.o `test -f 'launchd_runtime.c' || echo '$(srcdir)/'`launchd_runtime.c; \
+ at am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/launchd-launchd_runtime.Tpo" "$(DEPDIR)/launchd-launchd_runtime.Po"; else rm -f "$(DEPDIR)/launchd-launchd_runtime.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='launchd_runtime.c' object='launchd-launchd_runtime.o' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -c -o launchd-launchd_runtime.o `test -f 'launchd_runtime.c' || echo '$(srcdir)/'`launchd_runtime.c
+
+launchd-launchd_runtime.obj: launchd_runtime.c
+ at am__fastdepCC_TRUE@	if $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -MT launchd-launchd_runtime.obj -MD -MP -MF "$(DEPDIR)/launchd-launchd_runtime.Tpo" -c -o launchd-launchd_runtime.obj `if test -f 'launchd_runtime.c'; then $(CYGPATH_W) 'launchd_runtime.c'; else $(CYGPATH_W) '$(srcdir)/launchd_runtime.c'; fi`; \
+ at am__fastdepCC_TRUE@	then mv -f "$(DEPDIR)/launchd-launchd_runtime.Tpo" "$(DEPDIR)/launchd-launchd_runtime.Po"; else rm -f "$(DEPDIR)/launchd-launchd_runtime.Tpo"; exit 1; fi
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	source='launchd_runtime.c' object='launchd-launchd_runtime.obj' libtool=no @AMDEPBACKSLASH@
+ at AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ at am__fastdepCC_FALSE@	$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(launchd_CFLAGS) $(CFLAGS) -c -o launchd-launchd_runtime.obj `if test -f 'launchd_runtime.c'; then $(CYGPATH_W) 'launchd_runtime.c'; else $(CYGPATH_W) '$(srcdir)/launchd_runtime.c'; fi`
 uninstall-info-am:
 install-man1: $(man1_MANS) $(man_MANS)
 	@$(NORMAL_INSTALL)
@@ -1021,9 +1038,9 @@
 @LIBS_ONLY_TRUE@	cp liblaunch.a $(DESTDIR)/usr/local/lib/system/liblaunch_debug.a
 @LIBS_ONLY_TRUE@	cp liblaunch_profile.a $(DESTDIR)/usr/local/lib/system/liblaunch_profile.a
 
- at LIBS_ONLY_FALSE@launchd_mach_ipc.c:: bootstrap.h bootstrapServer.h notifyServer.h launchd_internal.h
+ at LIBS_ONLY_FALSE@launchd_runtime.c:: notifyServer.h launchd_internal.h
+ at LIBS_ONLY_FALSE@launchd_mach_ipc.c:: bootstrap.h bootstrapServer.h
 @LIBS_ONLY_FALSE at launchd_core_logic.c:: bootstrap.h mpm_reply.h
- at LIBS_ONLY_FALSE@launchd.c:: bootstrap.h launchd_internalServer.h launchd_internal.h notifyServer.h bootstrapServer.h
 
 @LIBS_ONLY_FALSE at notifyServer.c notifyServer.h: /usr/include/mach/notify.defs
 @LIBS_ONLY_FALSE@	mig $(MIGFLAGS) -header /dev/null -user /dev/null -sheader notifyServer.h /usr/include/mach/notify.defs

Modified: trunk/launchd/src/init.c
===================================================================
--- trunk/launchd/src/init.c	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/init.c	2006-09-11 21:08:28 UTC (rev 22850)
@@ -87,6 +87,7 @@
 #include <termios.h>
 
 #include "launchd.h"
+#include "launchd_runtime.h"
 
 #define _PATH_RUNCOM            "/etc/rc"
 

Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/launchd.c	2006-09-11 21:08:28 UTC (rev 22850)
@@ -59,7 +59,6 @@
 #include <dlfcn.h>
 #include <dirent.h>
 #include <string.h>
-#include <pthread.h>
 #include <setjmp.h>
 
 #include "bootstrap_public.h"
@@ -67,25 +66,10 @@
 #include "launch.h"
 #include "launch_priv.h"
 #include "launchd.h"
+#include "launchd_runtime.h"
 #include "launchd_core_logic.h"
 #include "launchd_unix_ipc.h"
 
-#include "launchd_internalServer.h"
-#include "launchd_internal.h"
-#include "notifyServer.h"
-#include "bootstrapServer.h"
-
-union MaxRequestSize {
-	union __RequestUnion__do_notify_subsystem req;
-	union __ReplyUnion__do_notify_subsystem rep;
-	union __RequestUnion__x_launchd_internal_subsystem req2;
-	union __ReplyUnion__x_launchd_internal_subsystem rep2;
-	union __RequestUnion__x_bootstrap_subsystem req3;
-	union __ReplyUnion__x_bootstrap_subsystem rep3;
-};
-
-static boolean_t launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply);
-
 #define PID1LAUNCHD_CONF "/etc/launchd.conf"
 #define LAUNCHD_CONF ".launchd.conf"
 #define LAUNCHCTL_PATH "/bin/launchctl"
@@ -93,13 +77,11 @@
 
 extern char **environ;
 
-static void async_callback(void);
 static void signal_callback(void *, struct kevent *);
 static void fs_callback(void);
 static void ppidexit_callback(void);
 static void pfsystem_callback(void *, struct kevent *);
 
-static kq_callback kqasync_callback = (kq_callback)async_callback;
 static kq_callback kqsignal_callback = signal_callback;
 static kq_callback kqfs_callback = (kq_callback)fs_callback;
 static kq_callback kqppidexit_callback = (kq_callback)ppidexit_callback;
@@ -112,12 +94,8 @@
 static void testfd_or_openfd(int fd, const char *path, int flags);
 static bool get_network_state(void);
 static void monitor_networking_state(void);
-static void *kqueue_demand_loop(void *arg);
 static void fatal_signal_handler(int sig);
 
-static pthread_t kqueue_demand_thread;
-static int mainkq = 0;
-static int asynckq = 0;
 static bool re_exec_in_single_user_mode = false;
 static char *pending_stdout = NULL;
 static char *pending_stderr = NULL;
@@ -128,8 +106,6 @@
 bool shutdown_in_progress = false;
 bool network_up = false;
 int batch_disabler_count = 0;
-mach_port_t launchd_internal_port = MACH_PORT_NULL;
-mach_port_t ipc_port_set = MACH_PORT_NULL;
 
 int
 main(int argc, char *const *argv)
@@ -147,7 +123,6 @@
 	const char *h = getenv("HOME");
 	const char *session_type = NULL;
 	const char *optargs = NULL;
-	launch_data_t ldresp, ldmsg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
 	job_t fbj = NULL;
 	struct stat sb;
 	size_t i, checkin_fdcnt = 0;
@@ -156,55 +131,68 @@
 	mach_port_t checkin_mport = MACH_PORT_NULL;
 	int ch, ker, logopts;
 
+	testfd_or_openfd(STDIN_FILENO, _PATH_DEVNULL, O_RDONLY);
+	testfd_or_openfd(STDOUT_FILENO, _PATH_DEVNULL, O_WRONLY);
+	testfd_or_openfd(STDERR_FILENO, _PATH_DEVNULL, O_WRONLY);
+
 	/* main() phase one: sanitize the process */
 
-	if (getpid() != 1 && (ldresp = launch_msg(ldmsg)) && launch_data_get_type(ldresp) == LAUNCH_DATA_DICTIONARY) {
-		const char *ldlabel = launch_data_get_string(launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_LABEL));
-		launch_data_t tmp;
+	if (getpid() != 1) {
+		launch_data_t ldresp, ldmsg = launch_data_new_string(LAUNCH_KEY_CHECKIN);
 
-		if ((tmp = launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_SOCKETS))) {
-			if ((tmp = launch_data_dict_lookup(tmp, "LaunchIPC"))) {
-				checkin_fdcnt = launch_data_array_get_count(tmp);
-				checkin_fds = alloca(sizeof(int) * checkin_fdcnt);
-				for (i = 0; i < checkin_fdcnt; i++) {
-					checkin_fds[i] = _fd(launch_data_get_fd(launch_data_array_get_index(tmp, i)));
+		if ((ldresp = launch_msg(ldmsg))) {
+			if (launch_data_get_type(ldresp) == LAUNCH_DATA_DICTIONARY) {
+				const char *ldlabel = launch_data_get_string(launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_LABEL));
+				launch_data_t tmp;
+
+				if ((tmp = launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_SOCKETS))) {
+					if ((tmp = launch_data_dict_lookup(tmp, "LaunchIPC"))) {
+						checkin_fdcnt = launch_data_array_get_count(tmp);
+						checkin_fds = alloca(sizeof(int) * checkin_fdcnt);
+						for (i = 0; i < checkin_fdcnt; i++) {
+							checkin_fds[i] = _fd(launch_data_get_fd(launch_data_array_get_index(tmp, i)));
+						}
+					}
 				}
+				if ((tmp = launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_MACHSERVICES))) {
+					if ((tmp = launch_data_dict_lookup(tmp, ldlabel))) {
+						checkin_mport = launch_data_get_machport(tmp);
+					}
+				}
 			}
-		}
-		if ((tmp = launch_data_dict_lookup(ldresp, LAUNCH_JOBKEY_MACHSERVICES))) {
-			if ((tmp = launch_data_dict_lookup(tmp, ldlabel))) {
-				checkin_mport = launch_data_get_machport(tmp);
-			}
-		}
-		launch_data_free(ldresp);
-	} else {
-		int sigi, fdi, dts = getdtablesize();
-		sigset_t emptyset;
+			launch_data_free(ldresp);
+		} else {
+			int sigi, fdi, dts = getdtablesize();
+			sigset_t emptyset;
 
-		for (fdi = STDERR_FILENO + 1; fdi < dts; fdi++)
-			close(fdi);
-		for (sigi = 1; sigi < NSIG; sigi++) {
-			switch (sigi) {
-			case SIGKILL:
-			case SIGSTOP:
-				break;
-			default:
-				launchd_assumes(signal(sigi, SIG_DFL) != SIG_ERR);
-				break;
+			/* We couldn't check-in.
+			 *
+			 * Assume the worst and clean up whatever mess our parent process left us with...
+			 */
+
+			for (fdi = STDERR_FILENO + 1; fdi < dts; fdi++)
+				close(fdi);
+			for (sigi = 1; sigi < NSIG; sigi++) {
+				switch (sigi) {
+				case SIGKILL:
+				case SIGSTOP:
+					break;
+				default:
+					launchd_assumes(signal(sigi, SIG_DFL) != SIG_ERR);
+					break;
+				}
 			}
+			sigemptyset(&emptyset);
+			launchd_assumes(sigprocmask(SIG_SETMASK, &emptyset, NULL) == 0);
 		}
-		sigemptyset(&emptyset);
-		launchd_assumes(sigprocmask(SIG_SETMASK, &emptyset, NULL) == 0);
+
+		launch_data_free(ldmsg);
 	}
 
-	launch_data_free(ldmsg);
+	launchd_runtime_init();
 
-	testfd_or_openfd(STDIN_FILENO, _PATH_DEVNULL, O_RDONLY|O_NOCTTY);
-	testfd_or_openfd(STDOUT_FILENO, _PATH_DEVNULL, O_WRONLY|O_NOCTTY);
-	testfd_or_openfd(STDERR_FILENO, _PATH_DEVNULL, O_WRONLY|O_NOCTTY);
+	/* main() phase two: parse arguments */
 
-	/* main phase two: parse arguments */
-
 	if (getpid() == 1) {
 		optargs = "s";
 	} else {
@@ -233,11 +221,6 @@
 	if (dflag)
 		launchd_assumes(daemon(0, 0) == 0);
 
-	launchd_assert((errno = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &ipc_port_set)) == KERN_SUCCESS);
-	launchd_assert(launchd_mport_create_recv(&launchd_internal_port) == KERN_SUCCESS);
-	launchd_assert(launchd_mport_make_send(launchd_internal_port) == KERN_SUCCESS);
-	launchd_assert((errno = mach_port_move_member(mach_task_self(), launchd_internal_port, ipc_port_set)) == KERN_SUCCESS);
-
 	logopts = LOG_PID|LOG_CONS;
 	if (Dflag)
 		logopts |= LOG_PERROR;
@@ -245,12 +228,6 @@
 	openlog(getprogname(), logopts, LOG_LAUNCHD);
 	setlogmask(LOG_UPTO(Dflag ? LOG_DEBUG : LOG_NOTICE));
 
-	launchd_assert((mainkq = kqueue()) != -1);
-
-	launchd_assert((asynckq = kqueue()) != -1);
-	
-	launchd_assert(kevent_mod(asynckq, EVFILT_READ, EV_ADD, 0, 0, &kqasync_callback) != -1);
-
 	sigemptyset(&blocked_signals);
 
 	for (i = 0; i < (sizeof(sigigns) / sizeof(int)); i++) {
@@ -327,16 +304,6 @@
 	if (fbj)
 		job_dispatch(fbj, true);
 
-	pthread_attr_t attr;
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
-	launchd_assert(pthread_create(&kqueue_demand_thread, &attr, kqueue_demand_loop, NULL) == 0);
-	pthread_attr_destroy(&attr); 
-
-	mach_msg_return_t msgr;
-	mach_msg_size_t mxmsgsz = sizeof(union MaxRequestSize) + MAX_TRAILER_SIZE;
-
 	if (getpid() == 1 && !job_active(rlcj))
 		init_pre_kevent();
 
@@ -346,12 +313,7 @@
 	launchd_assumes(signal(SIGBUS, fatal_signal_handler) != SIG_ERR);
 	launchd_assumes(signal(SIGSEGV, fatal_signal_handler) != SIG_ERR);
 
-	for (;;) {
-		msgr = mach_msg_server(launchd_internal_demux, mxmsgsz, ipc_port_set,
-				MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) |
-				MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
-		launchd_assumes(msgr == MACH_MSG_SUCCESS);
-	}
+	launchd_runtime();
 }
 
 void
@@ -360,56 +322,6 @@
 	longjmp(doom_doom_doom, sig);
 }
 
-void *
-kqueue_demand_loop(void *arg __attribute__((unused)))
-{
-	fd_set rfds;
-
-	for (;;) {
-		FD_ZERO(&rfds);
-		FD_SET(mainkq, &rfds);
-		if (launchd_assumes(select(mainkq + 1, &rfds, NULL, NULL, NULL) == 1))
-			launchd_assumes(handle_kqueue(launchd_internal_port, mainkq) == 0);
-	}
-
-	return NULL;
-}
-
-kern_return_t
-x_handle_kqueue(mach_port_t junk __attribute__((unused)), integer_t fd)
-{
-	struct timespec ts = { 0, 0 };
-	struct kevent kev;
-	int kevr;
-
-	launchd_assumes((kevr = kevent(fd, NULL, 0, &kev, 1, &ts)) != -1);
-
-	if (kevr == 1)
-		(*((kq_callback *)kev.udata))(kev.udata, &kev);
-
-	if (shutdown_in_progress && total_children == 0) {
-		mach_init_reap();
-
-		shutdown_in_progress = false;
-
-		if (getpid() != 1) {
-			exit(EXIT_SUCCESS);
-		} else if (re_exec_in_single_user_mode) {
-			re_exec_in_single_user_mode = false;
-			launchd_assumes(execl("/sbin/launchd", "/sbin/launchd", "-s", NULL) != -1);
-		}
-	}
-
-	if (getpid() == 1) {
-		if (rlcj && job_active(rlcj))
-			goto out;
-		init_pre_kevent();
-	}
-
-out:
-	return 0;
-}
-
 void
 pid1_magic_init(bool sflag)
 {
@@ -445,24 +357,6 @@
 }
 
 int
-kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata)
-{
-	struct kevent kev;
-	int q = mainkq;
-
-	if (EVFILT_TIMER == filter || EVFILT_VNODE == filter)
-		q = asynckq;
-
-	if (flags & EV_ADD && !launchd_assumes(udata != NULL)) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	EV_SET(&kev, ident, filter, flags, fflags, data, udata);
-	return kevent(q, &kev, 1, NULL, 0, NULL);
-}
-
-int
 _fd(int fd)
 {
 	if (fd >= 0)
@@ -489,7 +383,7 @@
 
 	shutdown_in_progress = true;
 
-	launchd_assumes(close(asynckq) != -1);
+	runtime_force_on_demand(true);
 	
 	rlcj = NULL;
 
@@ -577,16 +471,6 @@
 }
 
 void
-async_callback(void)
-{
-	struct timespec timeout = { 0, 0 };
-	struct kevent kev;
-
-	if (launchd_assumes(kevent(asynckq, NULL, 0, &kev, 1, &timeout) == 1))
-		(*((kq_callback *)kev.udata))(kev.udata, &kev);
-}
-
-void
 testfd_or_openfd(int fd, const char *path, int flags)
 {
 	int tmpfd;
@@ -594,7 +478,7 @@
 	if (-1 != (tmpfd = dup(fd))) {
 		launchd_assumes(close(tmpfd) == 0);
 	} else {
-		if (-1 == (tmpfd = open(path, flags))) {
+		if (-1 == (tmpfd = open(path, flags | O_NOCTTY, DEFFILEMODE))) {
 			syslog(LOG_ERR, "open(\"%s\", ...): %m", path);
 		} else if (tmpfd != fd) {
 			launchd_assumes(dup2(tmpfd, fd) != -1);
@@ -632,10 +516,10 @@
 		batch_disabler_count--;
 		c->disabled_batch = 0;
 		if (batch_disabler_count == 0)
-			kevent_mod(asynckq, EVFILT_READ, EV_ENABLE, 0, 0, &kqasync_callback);
+			runtime_force_on_demand(false);
 	} else if (!e && !c->disabled_batch) {
 		if (batch_disabler_count == 0)
-			kevent_mod(asynckq, EVFILT_READ, EV_DISABLE, 0, 0, &kqasync_callback);
+			runtime_force_on_demand(true);
 		batch_disabler_count++;
 		c->disabled_batch = 1;
 	}
@@ -756,21 +640,22 @@
 	return false;
 }
 
-boolean_t
-launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply)
+void
+launchd_post_kevent(void)
 {
-	if (gc_this_job) {
-		job_remove(gc_this_job);
-		gc_this_job = NULL;
-	}
+	if (shutdown_in_progress && total_children == 0) {
+		shutdown_in_progress = false;
 
-	if (Request->msgh_local_port == launchd_internal_port) {
-		if (launchd_internal_server_routine(Request))
-			return launchd_internal_server(Request, Reply);
-	} else {
-		if (bootstrap_server_routine(Request))
-			return bootstrap_server(Request, Reply);
+		if (getpid() != 1) {
+			exit(EXIT_SUCCESS);
+		} else if (re_exec_in_single_user_mode) {
+			re_exec_in_single_user_mode = false;
+			launchd_assumes(execl("/sbin/launchd", "/sbin/launchd", "-s", NULL) != -1);
+		}
 	}
-
-	return notify_server(Request, Reply);
+	if (getpid() == 1) {
+		if (rlcj && job_active(rlcj))
+			return;
+		init_pre_kevent();
+	}
 }

Modified: trunk/launchd/src/launchd.h
===================================================================
--- trunk/launchd/src/launchd.h	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/launchd.h	2006-09-11 21:08:28 UTC (rev 22850)
@@ -23,59 +23,34 @@
 #include <mach/mach.h>
 #include <mach/port.h>
 #include "launch.h"
+#include "launchd_runtime.h"
 #include "bootstrap_public.h"
 
-/*
- * Use launchd_assumes() when we can recover, even if it means we leak or limp along.
- *
- * Use launchd_assert() for core initialization routines.
- */
-#define launchd_assumes(e)	\
-	(__builtin_expect(!(e), 0) ? _log_launchd_bug(__rcs_file_version__, __FILE__, __LINE__, #e), false : true)
-
-#define launchd_blame(e, b)	\
-	(__builtin_expect(!(e), 0) ? syslog(LOG_DEBUG, "Encountered bug: %d", b), false : true)
-
-#define launchd_assert(e)	launchd_assumes(e) ? true : abort();
-
 #define FIRSTBORN_LABEL "com.apple.launchd.firstborn"
 #define READCONF_LABEL "com.apple.launchd.readconfig"
 
 struct kevent;
 struct conncb;
 
-typedef void (*kq_callback)(void *, struct kevent *);
-
 extern kq_callback kqsimple_zombie_reaper;
 extern sigset_t blocked_signals;
 extern bool shutdown_in_progress;
 extern bool network_up;
 extern int batch_disabler_count;
-extern mach_port_t launchd_internal_port;
-extern mach_port_t ipc_port_set;
+extern mach_port_t inherited_bootstrap_port;
 
 bool init_check_pid(pid_t);
 
-int kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata);
 void batch_job_enable(bool e, struct conncb *c);
 
 launch_data_t launchd_setstdio(int d, launch_data_t o);
 void launchd_SessionCreate(void);
 void launchd_shutdown(void);
 void launchd_single_user(void);
+void launchd_post_kevent(void);
 pid_t launchd_fork(void);
 boolean_t launchd_mach_ipc_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply);
 
-kern_return_t launchd_set_bport(mach_port_t name);
-kern_return_t launchd_get_bport(mach_port_t *name);
-kern_return_t launchd_mport_notify_req(mach_port_t name, mach_msg_id_t which);
-kern_return_t launchd_mport_notify_cancel(mach_port_t name, mach_msg_id_t which);
-kern_return_t launchd_mport_request_callback(mach_port_t name, void *obj, bool readmsg);
-kern_return_t launchd_mport_create_recv(mach_port_t *name);
-kern_return_t launchd_mport_deallocate(mach_port_t name);
-kern_return_t launchd_mport_make_send(mach_port_t name);
-kern_return_t launchd_mport_close_recv(mach_port_t name);
-
 void init_boot(bool sflag);
 void init_pre_kevent(void);
 
@@ -84,12 +59,9 @@
 
 void mach_start_shutdown(void);
 void mach_init_init(mach_port_t, mach_port_t, name_array_t, mach_port_array_t, mach_msg_type_number_t);
-void mach_init_reap(void);
 
 int _fd(int fd);
 
-void _log_launchd_bug(const char *rcs_rev, const char *path, unsigned int line, const char *test);
-
 bool progeny_check(pid_t p);
 
 #endif

Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/launchd_core_logic.c	2006-09-11 21:08:28 UTC (rev 22850)
@@ -72,6 +72,7 @@
 #include "launch.h"
 #include "launch_priv.h"
 #include "launchd.h"
+#include "launchd_runtime.h"
 #include "launchd_core_logic.h"
 #include "launchd_unix_ipc.h"
 #include "bootstrap_private.h"
@@ -1066,6 +1067,14 @@
 	bool is_wp = false;
 
 	switch (key[0]) {
+	case 'l':
+	case 'L':
+		if (strcasecmp(key, LAUNCH_JOBKEY_LIMITLOADTOHOSTS) == 0) {
+			return;
+		} else if (strcasecmp(key, LAUNCH_JOBKEY_LIMITLOADFROMHOSTS) == 0) {
+			return;
+		}
+		break;
 	case 'q':
 	case 'Q':
 		if (strcasecmp(key, LAUNCH_JOBKEY_QUEUEDIRECTORIES) == 0) {
@@ -1229,6 +1238,35 @@
 	return NULL;
 }
 
+static job_t 
+job_find_by_port2(job_t j, mach_port_t p)
+{
+	struct machservice *ms;
+	job_t jr, ji;
+
+	if (j->bs_port == p)
+		return j;
+
+	SLIST_FOREACH(ms, &j->machservices, sle) {
+		if (ms->port == p)
+			return j;
+	}
+
+	SLIST_FOREACH(ji, &j->jobs, sle) {
+		if ((jr = job_find_by_port2(ji, p)))
+			return jr;
+	}
+
+	errno = ESRCH;
+	return NULL;
+}
+
+job_t 
+job_find_by_port(mach_port_t p)
+{
+	return job_find_by_port2(root_job, p);
+}
+
 void
 job_export_all2(job_t j, launch_data_t where)
 {

Modified: trunk/launchd/src/launchd_mach_ipc.c
===================================================================
--- trunk/launchd/src/launchd_mach_ipc.c	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/launchd_mach_ipc.c	2006-09-11 21:08:28 UTC (rev 22850)
@@ -45,7 +45,6 @@
 #include <sys/socket.h>
 #include <bsm/libbsm.h>
 #include <unistd.h>
-#include <pthread.h>
 #include <errno.h>
 #include <string.h>
 #include <ctype.h>
@@ -58,10 +57,9 @@
 #include "bootstrap_private.h"
 #include "bootstrap.h"
 #include "bootstrapServer.h"
-#include "notifyServer.h"
 #include "launchd_internal.h"
-#include "launchd_internalServer.h"
 #include "launchd.h"
+#include "launchd_runtime.h"
 #include "launchd_core_logic.h"
 #include "launch_priv.h"
 #include "launchd_unix_ipc.h"
@@ -78,70 +76,22 @@
 static au_asid_t inherited_asid = 0;
 
 static bool canReceive(mach_port_t);
-static void init_ports(void);
-static void *mport_demand_loop(void *arg);
 static void audit_token_to_launchd_cred(audit_token_t au_tok, struct ldcred *ldc);
 
-static mach_port_t inherited_bootstrap_port = MACH_PORT_NULL;
-static mach_port_t demand_port_set = MACH_PORT_NULL;
-static size_t port_to_obj_size = 0;
-static void **port_to_obj = NULL;
-static pthread_t demand_thread;
+mach_port_t inherited_bootstrap_port = MACH_PORT_NULL;
 
 static bool trusted_client_check(job_t j, struct ldcred *ldc);
 
-job_t 
-job_find_by_port(mach_port_t mp)
-{
-	return port_to_obj[MACH_PORT_INDEX(mp)];
-}
-
-kern_return_t
-x_handle_mport(mach_port_t junk __attribute__((unused)))
-{
-	mach_port_name_array_t members;
-	mach_msg_type_number_t membersCnt;
-	mach_port_status_t status;
-	mach_msg_type_number_t statusCnt;
-	struct kevent kev;
-	unsigned int i;
-
-	if (!launchd_assumes(mach_port_get_set_status(mach_task_self(), demand_port_set, &members, &membersCnt) == KERN_SUCCESS))
-		return 1; 
-
-	for (i = 0; i < membersCnt; i++) {
-		statusCnt = MACH_PORT_RECEIVE_STATUS_COUNT;
-		if (mach_port_get_attributes(mach_task_self(), members[i], MACH_PORT_RECEIVE_STATUS,
-					(mach_port_info_t)&status, &statusCnt) != KERN_SUCCESS)
-			continue;
-
-		if (status.mps_msgcount) {
-			EV_SET(&kev, members[i], EVFILT_MACHPORT, 0, 0, 0, job_find_by_port(members[i]));
-			(*((kq_callback *)kev.udata))(kev.udata, &kev);
-			/* the callback may have tainted our ability to continue this for loop */
-			break;
-		}
-	}
-
-	launchd_assumes(vm_deallocate(mach_task_self(), (vm_address_t)members,
-				(vm_size_t) membersCnt * sizeof(mach_port_name_t)) == KERN_SUCCESS);
-
-	return 0;
-}
-
 void
 mach_init_init(mach_port_t req_port, mach_port_t checkin_port,
 		name_array_t l2l_names, mach_port_array_t l2l_ports, mach_msg_type_number_t l2l_cnt)
 {
 	mach_msg_type_number_t l2l_i;
 	auditinfo_t inherited_audit;
-	pthread_attr_t attr;
 
 	getaudit(&inherited_audit);
 	inherited_asid = inherited_audit.ai_asid;
 
-	init_ports();
-
 	launchd_assert((root_job = job_new_bootstrap(NULL, req_port ? req_port : mach_task_self(), checkin_port)) != NULL);
 
 	launchd_assumes(launchd_get_bport(&inherited_bootstrap_port) == KERN_SUCCESS);
@@ -152,14 +102,6 @@
 	/* We set this explicitly as we start each child */
 	launchd_assumes(launchd_set_bport(MACH_PORT_NULL) == KERN_SUCCESS);
 
-	pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
-	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
-
-	launchd_assert(pthread_create(&demand_thread, &attr, mport_demand_loop, NULL) == 0);
-
-	pthread_attr_destroy(&attr);
-
 	/* cut off the Libc cache, we don't want to deadlock against ourself */
 	bootstrap_port = MACH_PORT_NULL;
 
@@ -174,50 +116,6 @@
 	}
 }
 
-void mach_init_reap(void)
-{
-	void *status;
-
-	launchd_assumes(mach_port_destroy(mach_task_self(), demand_port_set) == KERN_SUCCESS);
-
-	launchd_assumes(pthread_join(demand_thread, &status) == 0);
-}
-
-void
-init_ports(void)
-{
-	launchd_assert((errno = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET,
-					&demand_port_set)) == KERN_SUCCESS);
-}
-
-void *
-mport_demand_loop(void *arg __attribute__((unused)))
-{
-	mach_msg_empty_rcv_t dummy;
-	kern_return_t kr;
-
-	for (;;) {
-		kr = mach_msg(&dummy.header, MACH_RCV_MSG|MACH_RCV_LARGE, 0, 0, demand_port_set, 0, MACH_PORT_NULL);
-		if (kr == MACH_RCV_PORT_CHANGED) {
-			break;
-		} else if (!launchd_assumes(kr == MACH_RCV_TOO_LARGE)) {
-			continue;
-		}
-		launchd_assumes(handle_mport(launchd_internal_port) == 0);
-	}
-
-	return NULL;
-}
-								
-boolean_t
-launchd_mach_ipc_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply)
-{
-	if (bootstrap_server_routine(Request))
-		return bootstrap_server(Request, Reply);
-
-	return notify_server(Request, Reply);
-}
-
 bool
 canReceive(mach_port_t port)
 {
@@ -229,94 +127,6 @@
 	return ((p_type & MACH_PORT_TYPE_RECEIVE) != 0);
 }
 
-kern_return_t
-launchd_set_bport(mach_port_t name)
-{
-	return errno = task_set_bootstrap_port(mach_task_self(), name);
-}
-
-kern_return_t
-launchd_get_bport(mach_port_t *name)
-{
-	return errno = task_get_bootstrap_port(mach_task_self(), name);
-}
-
-kern_return_t
-launchd_mport_notify_req(mach_port_t name, mach_msg_id_t which)
-{
-	mach_port_mscount_t msgc = (which == MACH_NOTIFY_NO_SENDERS) ? 1 : 0;
-	mach_port_t previous, where = (which == MACH_NOTIFY_NO_SENDERS) ? name : launchd_internal_port;
-
-	if (which == MACH_NOTIFY_NO_SENDERS) {
-		/* Always make sure the send count is zero, in case a receive right is reused */
-		errno = mach_port_set_mscount(mach_task_self(), name, 0);
-		if (errno != KERN_SUCCESS)
-			return errno;
-	}
-
-	errno = mach_port_request_notification(mach_task_self(), name, which, msgc, where,
-			MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
-
-	if (errno == 0 && previous != MACH_PORT_NULL)
-		launchd_assumes(launchd_mport_deallocate(previous) == KERN_SUCCESS);
-
-	return errno;
-}
-
-kern_return_t
-launchd_mport_request_callback(mach_port_t name, void *obj, bool readmsg)
-{
-	size_t needed_size;
-
-	if (!obj)
-		return errno = mach_port_move_member(mach_task_self(), name, MACH_PORT_NULL);
-
-	needed_size = (MACH_PORT_INDEX(name) + 1) * sizeof(void *);
-
-	if (needed_size > port_to_obj_size) {
-		if (port_to_obj == NULL) {
-			launchd_assumes((port_to_obj = calloc(1, needed_size * 2)) != NULL);
-		} else {
-			launchd_assumes((port_to_obj = reallocf(port_to_obj, needed_size * 2)) != NULL);
-			memset((uint8_t *)port_to_obj + port_to_obj_size, 0, needed_size * 2 - port_to_obj_size);
-		}
-		port_to_obj_size = needed_size * 2;
-	}
-
-	port_to_obj[MACH_PORT_INDEX(name)] = obj;
-
-	return errno = mach_port_move_member(mach_task_self(), name, readmsg ? ipc_port_set : demand_port_set);
-}
-
-kern_return_t
-launchd_mport_make_send(mach_port_t name)
-{
-	return errno = mach_port_insert_right(mach_task_self(), name, name, MACH_MSG_TYPE_MAKE_SEND);
-}
-
-kern_return_t
-launchd_mport_close_recv(mach_port_t name)
-{
-	if (launchd_assumes(port_to_obj != NULL)) {
-		port_to_obj[MACH_PORT_INDEX(name)] = NULL;
-		return errno = mach_port_mod_refs(mach_task_self(), name, MACH_PORT_RIGHT_RECEIVE, -1);
-	} else {
-		return errno = KERN_FAILURE;
-	}
-}
-
-kern_return_t
-launchd_mport_create_recv(mach_port_t *name)
-{
-	return errno = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, name);
-}
-
-kern_return_t
-launchd_mport_deallocate(mach_port_t name)
-{
-	return errno = mach_port_deallocate(mach_task_self(), name);
-}
-
 void
 audit_token_to_launchd_cred(audit_token_t au_tok, struct ldcred *ldc)
 {
@@ -810,81 +620,6 @@
 	return BOOTSTRAP_SUCCESS;
 }
 
-kern_return_t
-do_mach_notify_port_destroyed(mach_port_t notify, mach_port_t rights)
-{
-	/* This message is sent to us when a receive right is returned to us. */
-
-	if (!job_ack_port_destruction(root_job, rights)) {
-		launchd_assumes(launchd_mport_close_recv(rights) == KERN_SUCCESS);
-	}
-
-	return KERN_SUCCESS;
-}
-
-kern_return_t
-do_mach_notify_port_deleted(mach_port_t notify, mach_port_name_t name)
-{
-	/* If we deallocate/destroy/mod_ref away a port with a pending notification,
-	 * the original notification message is replaced with this message.
-	 *
-	 * To quote a Mach kernel expert, "the kernel has a send-once right that has
-	 * to be used somehow."
-	 */
-	return KERN_SUCCESS;
-}
-
-kern_return_t
-do_mach_notify_no_senders(mach_port_t notify, mach_port_mscount_t mscount)
-{
-	job_t j = job_find_by_port(notify);
-
-	/* This message is sent to us when the last customer of one of our objects
-	 * goes away.
-	 */
-
-	if (!launchd_assumes(j != NULL))
-		return KERN_FAILURE;
-
-	job_ack_no_senders(j);
-
-	return KERN_SUCCESS;
-}
-
-kern_return_t
-do_mach_notify_send_once(mach_port_t notify)
-{
-	/*
-	 * This message is sent to us every time we close a port that we have
-	 * outstanding Mach notification requests on. We can safely ignore
-	 * this message.
-	 */
-	return KERN_SUCCESS;
-}
-
-kern_return_t
-do_mach_notify_dead_name(mach_port_t notify, mach_port_name_t name)
-{
-	/* This message is sent to us when one of our send rights no longer has
-	 * a receiver somewhere else on the system.
-	 */
-
-	if (name == inherited_bootstrap_port) {
-		launchd_assumes(launchd_mport_deallocate(name) == KERN_SUCCESS);
-		inherited_bootstrap_port = MACH_PORT_NULL;
-	}
-		
-	job_delete_anything_with_port(root_job, name);
-
-	/* A dead-name notification about a port appears to increment the
-	 * rights on said port. Let's deallocate it so that we don't leak
-	 * dead-name ports.
-	 */
-	launchd_assumes(launchd_mport_deallocate(name) == KERN_SUCCESS);
-
-	return KERN_SUCCESS;
-}
-
 bool
 trusted_client_check(job_t j, struct ldcred *ldc)
 {

Copied: trunk/launchd/src/launchd_runtime.c (from rev 22841, trunk/launchd/src/launchd_mach_ipc.c)
===================================================================
--- trunk/launchd/src/launchd_runtime.c	                        (rev 0)
+++ trunk/launchd/src/launchd_runtime.c	2006-09-11 21:08:28 UTC (rev 22850)
@@ -0,0 +1,404 @@
+/*
+ * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+static const char *const __rcs_file_version__ = "$Revision$";
+
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/boolean.h>
+#include <mach/message.h>
+#include <mach/notify.h>
+#include <mach/mig_errors.h>
+#include <mach/mach_traps.h>
+#include <mach/mach_interface.h>
+#include <mach/host_info.h>
+#include <mach/mach_host.h>
+#include <mach/exception.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/event.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <bsm/libbsm.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <syslog.h>
+
+#include "launchd_runtime.h"
+
+#include "launchd_internalServer.h"
+#include "launchd_internal.h"
+#include "notifyServer.h"
+
+/* We shouldn't be including these */
+#include "launch.h"
+#include "launchd.h"
+#include "launchd_core_logic.h"
+#include "bootstrapServer.h"
+
+static mach_port_t ipc_port_set = MACH_PORT_NULL;
+static mach_port_t demand_port_set = MACH_PORT_NULL;
+static mach_port_t launchd_internal_port = MACH_PORT_NULL;
+static int mainkq = -1;
+static int asynckq = -1;
+
+static pthread_t kqueue_demand_thread;
+static pthread_t demand_thread;;
+
+static void *mport_demand_loop(void *arg);
+static void *kqueue_demand_loop(void *arg);
+
+static void async_callback(void);
+static kq_callback kqasync_callback = (kq_callback)async_callback;
+
+void
+launchd_runtime_init(void)
+{
+	pthread_attr_t attr;
+
+	launchd_assert((mainkq = kqueue()) != -1);
+	launchd_assert((asynckq = kqueue()) != -1);
+
+	launchd_assert(kevent_mod(asynckq, EVFILT_READ, EV_ADD, 0, 0, &kqasync_callback) != -1);
+
+	launchd_assert((errno = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &demand_port_set)) == KERN_SUCCESS);
+	launchd_assert((errno = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &ipc_port_set)) == KERN_SUCCESS);
+
+	launchd_assert(launchd_mport_create_recv(&launchd_internal_port) == KERN_SUCCESS);
+	launchd_assert(launchd_mport_make_send(launchd_internal_port) == KERN_SUCCESS);
+	launchd_assert((errno = mach_port_move_member(mach_task_self(), launchd_internal_port, ipc_port_set)) == KERN_SUCCESS);
+
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+	launchd_assert(pthread_create(&kqueue_demand_thread, &attr, kqueue_demand_loop, NULL) == 0);
+	pthread_attr_destroy(&attr);
+
+        pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN);
+	launchd_assert(pthread_create(&demand_thread, &attr, mport_demand_loop, NULL) == 0);
+	pthread_attr_destroy(&attr);
+}
+
+void *
+mport_demand_loop(void *arg __attribute__((unused)))
+{
+	mach_msg_empty_rcv_t dummy;
+	kern_return_t kr;
+
+	for (;;) {
+		kr = mach_msg(&dummy.header, MACH_RCV_MSG|MACH_RCV_LARGE, 0, 0, demand_port_set, 0, MACH_PORT_NULL);
+		if (kr == MACH_RCV_PORT_CHANGED) {
+			break;
+		} else if (!launchd_assumes(kr == MACH_RCV_TOO_LARGE)) {
+			continue;
+		}
+		launchd_assumes(handle_mport(launchd_internal_port) == 0);
+	}
+
+	return NULL;
+}
+
+kern_return_t
+x_handle_mport(mach_port_t junk __attribute__((unused)))
+{
+	mach_port_name_array_t members;
+	mach_msg_type_number_t membersCnt;
+	mach_port_status_t status;
+	mach_msg_type_number_t statusCnt;
+	struct kevent kev;
+	unsigned int i;
+
+	if (!launchd_assumes(mach_port_get_set_status(mach_task_self(), demand_port_set, &members, &membersCnt) == KERN_SUCCESS))
+		return 1;
+
+	for (i = 0; i < membersCnt; i++) {
+		statusCnt = MACH_PORT_RECEIVE_STATUS_COUNT;
+		if (mach_port_get_attributes(mach_task_self(), members[i], MACH_PORT_RECEIVE_STATUS, (mach_port_info_t)&status,
+					&statusCnt) != KERN_SUCCESS) {
+			continue;
+		}
+		if (status.mps_msgcount) {
+			EV_SET(&kev, members[i], EVFILT_MACHPORT, 0, 0, 0, job_find_by_port(members[i]));
+			(*((kq_callback *)kev.udata))(kev.udata, &kev);
+			/* the callback may have tainted our ability to continue this for loop */
+			break;
+		}
+	}
+
+	launchd_assumes(vm_deallocate(mach_task_self(), (vm_address_t)members,
+				(vm_size_t) membersCnt * sizeof(mach_port_name_t)) == KERN_SUCCESS);
+
+	return 0;
+}
+
+void *
+kqueue_demand_loop(void *arg __attribute__((unused)))
+{
+	fd_set rfds;
+
+	for (;;) {
+		FD_ZERO(&rfds);
+		FD_SET(mainkq, &rfds);
+		if (launchd_assumes(select(mainkq + 1, &rfds, NULL, NULL, NULL) == 1))
+			launchd_assumes(handle_kqueue(launchd_internal_port, mainkq) == 0);
+	}
+
+	return NULL;
+}
+
+kern_return_t
+x_handle_kqueue(mach_port_t junk __attribute__((unused)), integer_t fd)
+{
+	struct timespec ts = { 0, 0 };
+	struct kevent kev;
+	int kevr;
+
+	launchd_assumes((kevr = kevent(fd, NULL, 0, &kev, 1, &ts)) != -1);
+
+	if (kevr == 1)
+		(*((kq_callback *)kev.udata))(kev.udata, &kev);
+
+	launchd_post_kevent();
+
+	return 0;
+}
+
+
+
+void
+launchd_runtime(void)
+{
+	mach_msg_return_t msgr;
+
+	for (;;) {
+		msgr = mach_msg_server(launchd_internal_demux, 10*1024, ipc_port_set,
+				MACH_RCV_LARGE |
+				MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT) |
+				MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0));
+		launchd_assumes(msgr == MACH_MSG_SUCCESS);
+	}
+}
+
+kern_return_t
+launchd_set_bport(mach_port_t name)
+{
+	return errno = task_set_bootstrap_port(mach_task_self(), name);
+}
+
+kern_return_t
+launchd_get_bport(mach_port_t *name)
+{
+	return errno = task_get_bootstrap_port(mach_task_self(), name);
+}
+
+kern_return_t
+launchd_mport_notify_req(mach_port_t name, mach_msg_id_t which)
+{
+	mach_port_mscount_t msgc = (which == MACH_NOTIFY_NO_SENDERS) ? 1 : 0;
+	mach_port_t previous, where = (which == MACH_NOTIFY_NO_SENDERS) ? name : launchd_internal_port;
+
+	if (which == MACH_NOTIFY_NO_SENDERS) {
+		/* Always make sure the send count is zero, in case a receive right is reused */
+		errno = mach_port_set_mscount(mach_task_self(), name, 0);
+		if (errno != KERN_SUCCESS)
+			return errno;
+	}
+
+	errno = mach_port_request_notification(mach_task_self(), name, which, msgc, where,
+			MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+
+	if (errno == 0 && previous != MACH_PORT_NULL)
+		launchd_assumes(launchd_mport_deallocate(previous) == KERN_SUCCESS);
+
+	return errno;
+}
+
+kern_return_t
+launchd_mport_request_callback(mach_port_t name, void *obj, bool readmsg)
+{
+	mach_port_t target_set = MACH_PORT_NULL;
+
+	if (obj) {
+		target_set = readmsg ? ipc_port_set : demand_port_set;
+	}
+
+	return errno = mach_port_move_member(mach_task_self(), name, target_set);
+}
+
+kern_return_t
+launchd_mport_make_send(mach_port_t name)
+{
+	return errno = mach_port_insert_right(mach_task_self(), name, name, MACH_MSG_TYPE_MAKE_SEND);
+}
+
+kern_return_t
+launchd_mport_close_recv(mach_port_t name)
+{
+	return errno = mach_port_mod_refs(mach_task_self(), name, MACH_PORT_RIGHT_RECEIVE, -1);
+}
+
+kern_return_t
+launchd_mport_create_recv(mach_port_t *name)
+{
+	return errno = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, name);
+}
+
+kern_return_t
+launchd_mport_deallocate(mach_port_t name)
+{
+	return errno = mach_port_deallocate(mach_task_self(), name);
+}
+
+int
+kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata)
+{
+	struct kevent kev;
+	int q = mainkq;
+
+	if (EVFILT_TIMER == filter || EVFILT_VNODE == filter)
+		q = asynckq;
+
+	if (flags & EV_ADD && !launchd_assumes(udata != NULL)) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	EV_SET(&kev, ident, filter, flags, fflags, data, udata);
+
+	return kevent(q, &kev, 1, NULL, 0, NULL);
+}
+
+void
+async_callback(void)
+{
+	struct timespec timeout = { 0, 0 };
+	struct kevent kev;
+
+	if (launchd_assumes(kevent(asynckq, NULL, 0, &kev, 1, &timeout) == 1)) {
+		(*((kq_callback *)kev.udata))(kev.udata, &kev);
+	}
+}
+
+void
+runtime_force_on_demand(bool b)
+{
+	launchd_assumes(kevent_mod(asynckq, EVFILT_READ, b ? EV_DISABLE : EV_ENABLE, 0, 0, &kqasync_callback) != -1);
+}
+
+boolean_t
+launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply)
+{
+	if (gc_this_job) {
+		job_remove(gc_this_job);
+		gc_this_job = NULL;
+	}
+
+	if (Request->msgh_local_port == launchd_internal_port) {
+		if (launchd_internal_server_routine(Request))
+			return launchd_internal_server(Request, Reply);
+	} else {
+		if (bootstrap_server_routine(Request))
+			return bootstrap_server(Request, Reply);
+	}
+
+	return notify_server(Request, Reply);
+}
+
+kern_return_t
+do_mach_notify_port_destroyed(mach_port_t notify, mach_port_t rights)
+{
+	/* This message is sent to us when a receive right is returned to us. */
+
+	if (!job_ack_port_destruction(root_job, rights)) {
+		launchd_assumes(launchd_mport_close_recv(rights) == KERN_SUCCESS);
+	}
+
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_port_deleted(mach_port_t notify, mach_port_name_t name)
+{
+	/* If we deallocate/destroy/mod_ref away a port with a pending
+	 * notification, the original notification message is replaced with
+	 * this message. To quote a Mach kernel expert, "the kernel has a
+	 * send-once right that has to be used somehow."
+	 */
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_no_senders(mach_port_t notify, mach_port_mscount_t mscount)
+{
+	job_t j = job_find_by_port(notify);
+
+	/* This message is sent to us when the last customer of one of our
+	 * objects goes away.
+	 */
+
+	if (!launchd_assumes(j != NULL))
+		return KERN_FAILURE;
+
+	job_ack_no_senders(j);
+
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_send_once(mach_port_t notify)
+{
+	/* This message is sent to us every time we close a port that we have
+	 * outstanding Mach notification requests on. We can safely ignore this
+	 * message.
+	 */
+
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+do_mach_notify_dead_name(mach_port_t notify, mach_port_name_t name)
+{
+	/* This message is sent to us when one of our send rights no longer has
+	 * a receiver somewhere else on the system.
+	 */
+
+	if (name == inherited_bootstrap_port) {
+		launchd_assumes(launchd_mport_deallocate(name) == KERN_SUCCESS);
+		inherited_bootstrap_port = MACH_PORT_NULL;
+	}
+
+	job_delete_anything_with_port(root_job, name);
+
+	/* A dead-name notification about a port appears to increment the
+	 * rights on said port. Let's deallocate it so that we don't leak
+	 * dead-name ports.
+	 */
+	launchd_assumes(launchd_mport_deallocate(name) == KERN_SUCCESS);
+
+	return KERN_SUCCESS;
+}

Copied: trunk/launchd/src/launchd_runtime.h (from rev 22841, trunk/launchd/src/launchd.h)
===================================================================
--- trunk/launchd/src/launchd_runtime.h	                        (rev 0)
+++ trunk/launchd/src/launchd_runtime.h	2006-09-11 21:08:28 UTC (rev 22850)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+#ifndef __LAUNCHD_RUNTIME_H__
+#define __LAUNCHD_RUNTIME_H__
+
+#include <mach/mach.h>
+
+/*
+ * Use launchd_assumes() when we can recover, even if it means we leak or limp along.
+ *
+ * Use launchd_assert() for core initialization routines.
+ */
+#define launchd_assumes(e)	\
+	(__builtin_expect(!(e), 0) ? _log_launchd_bug(__rcs_file_version__, __FILE__, __LINE__, #e), false : true)
+
+#define launchd_blame(e, b)	\
+	(__builtin_expect(!(e), 0) ? syslog(LOG_DEBUG, "Encountered bug: %d", b), false : true)
+
+#define launchd_assert(e)	launchd_assumes(e) ? true : abort();
+
+void _log_launchd_bug(const char *rcs_rev, const char *path, unsigned int line, const char *test);
+
+typedef void (*kq_callback)(void *, struct kevent *);
+
+boolean_t launchd_internal_demux(mach_msg_header_t *Request, mach_msg_header_t *Reply);
+
+void launchd_runtime_init(void);
+void launchd_runtime(void) __attribute__((noreturn));
+
+void runtime_force_on_demand(bool);
+
+int kevent_mod(uintptr_t ident, short filter, u_short flags, u_int fflags, intptr_t data, void *udata);
+
+kern_return_t launchd_set_bport(mach_port_t name);
+kern_return_t launchd_get_bport(mach_port_t *name);
+kern_return_t launchd_mport_notify_req(mach_port_t name, mach_msg_id_t which);
+kern_return_t launchd_mport_notify_cancel(mach_port_t name, mach_msg_id_t which);
+kern_return_t launchd_mport_request_callback(mach_port_t name, void *obj, bool readmsg);
+kern_return_t launchd_mport_create_recv(mach_port_t *name);
+kern_return_t launchd_mport_deallocate(mach_port_t name);
+kern_return_t launchd_mport_make_send(mach_port_t name);
+kern_return_t launchd_mport_close_recv(mach_port_t name);
+
+#endif

Modified: trunk/launchd/src/launchd_unix_ipc.c
===================================================================
--- trunk/launchd/src/launchd_unix_ipc.c	2006-09-08 16:26:14 UTC (rev 22849)
+++ trunk/launchd/src/launchd_unix_ipc.c	2006-09-11 21:08:28 UTC (rev 22850)
@@ -48,6 +48,7 @@
 #include "launch.h"
 #include "launch_priv.h"
 #include "launchd.h"
+#include "launchd_runtime.h"
 #include "launchd_core_logic.h"
 #include "launchd_unix_ipc.h"
 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20060911/672cd786/attachment.html


More information about the launchd-changes mailing list