[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