[launchd-changes] [23574] trunk/launchd/src
source_changes at macosforge.org
source_changes at macosforge.org
Thu Mar 27 14:18:34 PDT 2008
Revision: 23574
http://trac.macosforge.org/projects/launchd/changeset/23574
Author: zarzycki at apple.com
Date: 2008-03-27 14:18:33 -0700 (Thu, 27 Mar 2008)
Log Message:
-----------
<rdar://problem/5752398> Need a darwin clean/dirty API
Modified Paths:
--------------
trunk/launchd/src/Makefile.am
trunk/launchd/src/Makefile.in
trunk/launchd/src/launchd.plist.5
trunk/launchd/src/launchd_core_logic.c
trunk/launchd/src/liblaunch_public.h
trunk/launchd/src/libvproc.c
trunk/launchd/src/libvproc_internal.h
trunk/launchd/src/libvproc_private.h
trunk/launchd/src/libvproc_public.h
trunk/launchd/src/protocol_job.defs
Modified: trunk/launchd/src/Makefile.am
===================================================================
--- trunk/launchd/src/Makefile.am 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/Makefile.am 2008-03-27 21:18:33 UTC (rev 23574)
@@ -1,5 +1,5 @@
CWARN = -Wall -Wextra -Waggregate-return -Wfloat-equal -Wshadow -Wpacked -Wmissing-prototypes -Wmissing-declarations -Werror # gcc4.2: -Wstrict-overflow=4 # -Wpadded -Wconversion -Wstrict-aliasing=2
-CTUNE = -fvisibility=hidden # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing
+CTUNE = -fvisibility=hidden -freorder-blocks # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing
CMISC = -isysroot $(SDKROOT) -F$(SDKROOT)/System/Library/PrivateFrameworks -D__MigTypeCheck=1 -Dmig_external=__private_extern__ -D_DARWIN_USE_64_BIT_INODE=1
AM_CFLAGS = $(CTUNE) $(CMISC) $(CWARN)
AM_LDFLAGS = -Wl,-syslibroot,$(SDKROOT)
@@ -57,7 +57,7 @@
SystemStarter_SOURCES = StartupItems.c IPC.c SystemStarter.c
endif
-launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -freorder-blocks
+launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS)
launchd_LDFLAGS = $(AM_LDFLAGS) -lbsm
launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c protocol_vprocServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c job_replyUser.c launchd_runtime.c launchd_runtime_kill.c job_forwardUser.c mach_excServer.c
Modified: trunk/launchd/src/Makefile.in
===================================================================
--- trunk/launchd/src/Makefile.in 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/Makefile.in 2008-03-27 21:18:33 UTC (rev 23574)
@@ -243,7 +243,7 @@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
CWARN = -Wall -Wextra -Waggregate-return -Wfloat-equal -Wshadow -Wpacked -Wmissing-prototypes -Wmissing-declarations -Werror # gcc4.2: -Wstrict-overflow=4 # -Wpadded -Wconversion -Wstrict-aliasing=2
-CTUNE = -fvisibility=hidden # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing
+CTUNE = -fvisibility=hidden -freorder-blocks # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing
CMISC = -isysroot $(SDKROOT) -F$(SDKROOT)/System/Library/PrivateFrameworks -D__MigTypeCheck=1 -Dmig_external=__private_extern__ -D_DARWIN_USE_64_BIT_INODE=1
AM_CFLAGS = $(CTUNE) $(CMISC) $(CWARN)
AM_LDFLAGS = -Wl,-syslibroot,$(SDKROOT)
@@ -262,7 +262,7 @@
@DO_EMBEDDED_MAGIC_FALSE@@LIBS_ONLY_FALSE at SystemStarter_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS)
@DO_EMBEDDED_MAGIC_FALSE@@LIBS_ONLY_FALSE at SystemStarter_LDFLAGS = $(AM_LDFLAGS) -framework CoreFoundation -framework IOKit
@DO_EMBEDDED_MAGIC_FALSE@@LIBS_ONLY_FALSE at SystemStarter_SOURCES = StartupItems.c IPC.c SystemStarter.c
- at LIBS_ONLY_FALSE@launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -freorder-blocks
+ at LIBS_ONLY_FALSE@launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS)
@LIBS_ONLY_FALSE at launchd_LDFLAGS = $(AM_LDFLAGS) -lbsm
@LIBS_ONLY_FALSE at launchd_SOURCES = launchd.c launchd_core_logic.c launchd_unix_ipc.c protocol_vprocServer.c notifyServer.c launchd_internalUser.c launchd_internalServer.c job_replyUser.c launchd_runtime.c launchd_runtime_kill.c job_forwardUser.c mach_excServer.c
@LIBS_ONLY_FALSE at launchproxy_LDFLAGS = $(AM_LDFLAGS) $(LIBS_SECURITY)
Modified: trunk/launchd/src/launchd.plist.5
===================================================================
--- trunk/launchd/src/launchd.plist.5 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/launchd.plist.5 2008-03-27 21:18:33 UTC (rev 23574)
@@ -123,6 +123,16 @@
to use the
.Xr glob 3
mechanism to update the program arguments before invocation.
+.It Sy EnableTransactions <boolean>
+This flag instructs
+.Nm launchd
+that the job promises to use
+.Xr vproc_transaction_begin 3
+and
+.Xr vproc_transaction_end 3
+to track outstanding transactions that need to be reconciled before the process can safely terminate. If no outstanding transactions are in progress, then
+.Nm launchd
+is free to send the SIGKILL signal.
.It Sy OnDemand <boolean>
This key was used in Mac OS X 10.4 to control whether a job was kept alive or not. The default was true.
This key has been deprecated and replaced in Mac OS X 10.5 with the more powerful KeepAlive option.
Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/launchd_core_logic.c 2008-03-27 21:18:33 UTC (rev 23574)
@@ -50,6 +50,7 @@
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/pipe.h>
+#include <sys/mman.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/in_var.h>
@@ -360,6 +361,7 @@
char *stdoutpath;
char *stderrpath;
char *alt_exc_handler;
+ struct vproc_shmem_s *shmem;
struct machservice *lastlookup;
unsigned int lastlookup_gennum;
#if HAVE_SANDBOX
@@ -384,14 +386,14 @@
uint64_t start_time;
uint32_t min_run_time;
uint32_t start_interval;
- unsigned short checkedin:1, anonymous:1, debug:1, inetcompat:1, inetcompat_wait:1,
+ bool checkedin:1, anonymous:1, debug:1, inetcompat:1, inetcompat_wait:1,
ondemand:1, session_create:1, low_pri_io:1, no_init_groups:1, priv_port_has_senders:1,
importing_global_env:1, importing_hard_limits:1, setmask:1, legacy_mach_job:1, start_pending:1,
globargv:1, wait4debugger:1, internal_exc_handler:1, stall_before_exec:1, only_once:1,
currently_ignored:1, forced_peers_to_demand_mode:1, setnice:1, hopefully_exits_last:1, removal_pending:1,
legacy_LS_job:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1, start_on_mount:1,
per_user:1, hopefully_exits_first:1, deny_unknown_mslookups:1, unload_at_mig_return:1, abandon_pg:1,
- poll_for_vfs_changes:1, deny_job_creation:1, __junk:11;
+ poll_for_vfs_changes:1, deny_job_creation:1, kill_via_shmem:1, sent_kill_via_shmem:1;
mode_t mask;
const char label[0];
};
@@ -561,19 +563,40 @@
INTERNAL_ABI void
job_stop(job_t j)
{
+ int32_t newval = 1;
+
if (unlikely(!j->p || j->anonymous)) {
return;
}
- job_assumes(j, runtime_kill(j->p, SIGTERM) != -1);
+ if (j->kill_via_shmem) {
+ if (j->shmem) {
+ if (!j->sent_kill_via_shmem) {
+ j->shmem->vp_shmem_flags |= VPROC_SHMEM_EXITING;
+ newval = __sync_sub_and_fetch(&j->shmem->vp_shmem_transaction_cnt, 1);
+ j->sent_kill_via_shmem = true;
+ } else {
+ newval = j->shmem->vp_shmem_transaction_cnt;
+ }
+ } else {
+ newval = -1;
+ }
+ }
+
j->sent_sigterm_time = runtime_get_opaque_time();
- if (j->exit_timeout) {
- job_assumes(j, kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER,
- EV_ADD|EV_ONESHOT, NOTE_SECONDS, j->exit_timeout, j) != -1);
+ if (newval < 0) {
+ job_kill(j);
+ } else {
+ job_assumes(j, runtime_kill(j->p, SIGTERM) != -1);
+
+ if (j->exit_timeout) {
+ job_assumes(j, kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER,
+ EV_ADD|EV_ONESHOT, NOTE_SECONDS, j->exit_timeout, j) != -1);
+ }
+
+ job_log(j, LOG_DEBUG, "Sent SIGTERM signal");
}
-
- job_log(j, LOG_DEBUG, "Sent SIGTERM signal");
}
INTERNAL_ABI launch_data_t
@@ -1453,6 +1476,9 @@
if (strcasecmp(key, LAUNCH_JOBKEY_ENABLEGLOBBING) == 0) {
j->globargv = value;
found_key = true;
+ } else if (strcasecmp(key, LAUNCH_JOBKEY_ENABLETRANSACTIONS) == 0) {
+ j->kill_via_shmem = value;
+ found_key = true;
} else if (strcasecmp(key, LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL) == 0) {
j->debug_before_kill = value;
found_key = true;
@@ -2203,6 +2229,10 @@
job_log(j, LOG_DEBUG, "Reaping");
+ if (j->shmem) {
+ job_assumes(j, munmap(j->shmem, getpagesize()) == 0);
+ }
+
if (unlikely(j->weird_bootstrap)) {
mach_msg_size_t mxmsgsz = sizeof(union __RequestUnion__job_mig_protocol_vproc_subsystem);
@@ -2335,6 +2365,7 @@
}
j->last_exit_status = status;
j->sent_sigkill = false;
+ j->sent_kill_via_shmem = false;
j->p = 0;
/*
@@ -5402,6 +5433,36 @@
}
kern_return_t
+job_mig_setup_shmem(job_t j, mach_port_t *shmem_port)
+{
+ memory_object_size_t size_of_page, size_of_page_orig;
+ kern_return_t kr;
+
+ if (!launchd_assumes(j != NULL)) {
+ return BOOTSTRAP_NO_MEMORY;
+ }
+
+ if (unlikely(j->anonymous)) {
+ return BOOTSTRAP_NOT_PRIVILEGED;
+ }
+
+ size_of_page_orig = size_of_page = getpagesize();
+
+ if (!job_assumes(j, j->shmem = mmap(NULL, size_of_page, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0))) {
+ return BOOTSTRAP_NO_MEMORY;
+ }
+
+ kr = mach_make_memory_entry_64(mach_task_self(), &size_of_page,
+ (memory_object_offset_t)((long)j->shmem), VM_PROT_DEFAULT, shmem_port, 0);
+
+ if (job_assumes(j, kr == 0)) {
+ job_assumes(j, size_of_page == size_of_page_orig);
+ }
+
+ return kr;
+}
+
+kern_return_t
job_mig_create_server(job_t j, cmd_t server_cmd, uid_t server_uid, boolean_t on_demand, mach_port_t *server_portp)
{
struct ldcred *ldc = runtime_get_caller_creds();
Modified: trunk/launchd/src/liblaunch_public.h
===================================================================
--- trunk/launchd/src/liblaunch_public.h 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/liblaunch_public.h 2008-03-27 21:18:33 UTC (rev 23574)
@@ -101,6 +101,7 @@
#define LAUNCH_JOBKEY_LAUNCHONLYONCE "LaunchOnlyOnce"
#define LAUNCH_JOBKEY_ABANDONPROCESSGROUP "AbandonProcessGroup"
#define LAUNCH_JOBKEY_POLICIES "Policies"
+#define LAUNCH_JOBKEY_ENABLETRANSACTIONS "EnableTransactions"
#define LAUNCH_JOBPOLICY_DENYCREATINGOTHERJOBS "DenyCreatingOtherJobs"
Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/libvproc.c 2008-03-27 21:18:33 UTC (rev 23574)
@@ -32,6 +32,7 @@
#include <unistd.h>
#include <syslog.h>
#include <pthread.h>
+#include <signal.h>
#if HAVE_QUARANTINE
#include <quarantine.h>
#endif
@@ -44,10 +45,142 @@
#include "reboot2.h"
+#define likely(x) __builtin_expect((bool)(x), true)
+#define unlikely(x) __builtin_expect((bool)(x), false)
+
static mach_port_t get_root_bootstrap_port(void);
+const char *__crashreporter_info__; /* this should get merged with other versions of the symbol */
+
static int64_t cached_pid = -1;
+static struct vproc_shmem_s *vproc_shmem;
+static void
+vproc_shmem_init(void)
+{
+ vm_address_t vm_addr = 0;
+ mach_port_t shmem_port;
+ kern_return_t kr;
+
+ kr = vproc_mig_setup_shmem(bootstrap_port, &shmem_port);
+
+ if (unlikely(kr)) {
+ abort();
+ }
+
+ kr = vm_map_64(mach_task_self(), &vm_addr, getpagesize(), 0, true, shmem_port, 0, false,
+ VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, VM_INHERIT_NONE);
+
+ if (unlikely(kr)) {
+ abort();
+ }
+
+ vproc_shmem = (struct vproc_shmem_s *)vm_addr;
+}
+
+vproc_transaction_t
+vproc_transaction_begin(vproc_t vp __attribute__((unused)))
+{
+ vproc_transaction_t vpt = (vproc_transaction_t)vproc_shmem_init; /* we need a "random" variable that is testable */
+
+ _basic_vproc_transaction_begin();
+
+ return vpt;
+}
+
+void
+_basic_vproc_transaction_begin(void)
+{
+ int64_t newval;
+
+ if (unlikely(vproc_shmem == NULL)) {
+ vproc_shmem_init();
+ if (vproc_shmem == NULL) {
+ return;
+ }
+ }
+
+ newval = __sync_add_and_fetch(&vproc_shmem->vp_shmem_transaction_cnt, 1);
+
+ if (unlikely(newval < 1)) {
+ if (vproc_shmem->vp_shmem_flags & VPROC_SHMEM_EXITING) {
+ raise(SIGKILL);
+ __crashreporter_info__ = "raise(SIGKILL) failed";
+ } else {
+ __crashreporter_info__ = "Unbalanced: vproc_transaction_begin()";
+ }
+ abort();
+ }
+}
+
+void
+vproc_transaction_end(vproc_t vp __attribute__((unused)), vproc_transaction_t vpt)
+{
+ if (unlikely(vpt != (vproc_transaction_t)vproc_shmem_init)) {
+ __crashreporter_info__ = "Bogus transaction handle passed to vproc_transaction_end() ";
+ abort();
+ }
+
+ _basic_vproc_transaction_end();
+}
+
+void
+_basic_vproc_transaction_end(void)
+{
+ int32_t newval = __sync_sub_and_fetch(&vproc_shmem->vp_shmem_transaction_cnt, 1);
+
+ if (unlikely(newval < 0)) {
+ if (vproc_shmem->vp_shmem_flags & VPROC_SHMEM_EXITING) {
+ raise(SIGKILL);
+ __crashreporter_info__ = "raise(SIGKILL) failed";
+ } else {
+ __crashreporter_info__ = "Unbalanced: vproc_transaction_end()";
+ }
+ abort();
+ }
+}
+
+vproc_standby_t
+vproc_standby_begin(vproc_t vp __attribute__((unused)))
+{
+ vproc_standby_t vpsb = (vproc_standby_t)vproc_shmem_init; /* we need a "random" variable that is testable */
+ int64_t newval;
+
+ if (unlikely(vproc_shmem == NULL)) {
+ vproc_shmem_init();
+ if (vproc_shmem == NULL) {
+ return NULL;
+ }
+ }
+
+ newval = __sync_add_and_fetch(&vproc_shmem->vp_shmem_standby_cnt, 1);
+
+ if (unlikely(newval < 1)) {
+ __crashreporter_info__ = "Unbalanced: vproc_standby_begin()";
+ abort();
+ }
+
+ return vpsb;
+}
+
+void
+vproc_standby_end(vproc_t vp __attribute__((unused)), vproc_standby_t vpt)
+{
+ int32_t newval;
+
+ if (unlikely(vpt != (vproc_standby_t)vproc_shmem_init)) {
+ __crashreporter_info__ = "Bogus standby handle passed to vproc_standby_end() ";
+ abort();
+ }
+
+ newval = __sync_sub_and_fetch(&vproc_shmem->vp_shmem_standby_cnt, 1);
+
+ if (unlikely(newval < 0)) {
+ __crashreporter_info__ = "Unbalanced: vproc_standby_end()";
+ abort();
+ }
+}
+
kern_return_t
_vproc_grab_subset(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright, launch_data_t *outval,
mach_port_array_t *ports, mach_msg_type_number_t *portCnt)
Modified: trunk/launchd/src/libvproc_internal.h
===================================================================
--- trunk/launchd/src/libvproc_internal.h 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/libvproc_internal.h 2008-03-27 21:18:33 UTC (rev 23574)
@@ -33,6 +33,14 @@
typedef pid_t * pid_array_t;
typedef mach_port_t vproc_mig_t;
+#define VPROC_SHMEM_EXITING 0x1
+
+struct vproc_shmem_s {
+ int32_t vp_shmem_transaction_cnt;
+ int32_t vp_shmem_standby_cnt;
+ int32_t vp_shmem_flags;
+};
+
#ifdef protocol_vproc_MSG_COUNT
/* HACK */
#include "launchd_core_logic.h"
Modified: trunk/launchd/src/libvproc_private.h
===================================================================
--- trunk/launchd/src/libvproc_private.h 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/libvproc_private.h 2008-03-27 21:18:33 UTC (rev 23574)
@@ -76,6 +76,9 @@
vproc_err_t _vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type);
+void _basic_vproc_transaction_begin(void);
+void _basic_vproc_transaction_end(void);
+
#pragma GCC visibility pop
__END_DECLS
Modified: trunk/launchd/src/libvproc_public.h
===================================================================
--- trunk/launchd/src/libvproc_public.h 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/libvproc_public.h 2008-03-27 21:18:33 UTC (rev 23574)
@@ -67,8 +67,8 @@
*
* launchd jobs should update their property lists accordingly.
*
- * LaunchServices uses private methods to coordinate whether GUI applications
- * have opted into this design.
+ * We plan to have LaunchServices use private methods to coordinate
+ * whether GUI applications have opted into this design.
*/
/*!
@@ -80,22 +80,28 @@
typedef struct vproc_transaction_s *vproc_transaction_t;
/*!
- * @function vproc_transaction_prepare
+ * @function vproc_transaction_begin
*
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
* @result
- * Returns an opaque handle to be passed to vproc_transaction_complete().
+ * Returns an opaque handle to be passed to vproc_transaction_end().
*
* @abstract
* Call this API before creating data that needs to be saved via I/O later.
*/
vproc_transaction_t
-vproc_transaction_prepare(void);
+vproc_transaction_begin(vproc_t virtual_proc);
/*!
- * @function vproc_transaction_complete
+ * @function vproc_transaction_end
*
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
* @param handle
- * The handle previously created with vproc_transaction_prepare().
+ * The handle previously created with vproc_transaction_begin().
*
* @abstract
* Call this API after the data has either been flushed or otherwise resolved.
@@ -104,7 +110,7 @@
* Calling this API with the same handle more than once is undefined.
*/
void
-vproc_transaction_complete(vproc_transaction_t handle);
+vproc_transaction_end(vproc_t virtual_proc, vproc_transaction_t handle);
/*!
* @typedef vproc_standby_t
@@ -115,23 +121,29 @@
typedef struct vproc_standby_s *vproc_standby_t;
/*!
- * @function vproc_standby_prepare
+ * @function vproc_standby_begin
*
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
* @result
- * Returns an opaque handle to be passed to vproc_standby_complete().
+ * Returns an opaque handle to be passed to vproc_standby_end().
*
* @abstract
* Call this API before registering notifications. For example: timers network
* state change, or when monitoring keyboard/mouse events.
*/
vproc_standby_t
-vproc_standby_prepare(void);
+vproc_standby_begin(vproc_t virtual_proc);
/*!
- * @function vproc_standby_complete
+ * @function vproc_standby_end
*
+ * @param virtual_proc
+ * This is meant for future API improvements. Pass NULL for now.
+ *
* @param handle
- * The handle previously created with vproc_standby_prepare().
+ * The handle previously created with vproc_standby_begin().
*
* @abstract
* Call this API when deregistering notifications.
@@ -140,7 +152,7 @@
* Calling this API with the same handle more than once is undefined.
*/
void
-vproc_standby_complete(vproc_standby_t handle);
+vproc_standby_end(vproc_t virtual_proc, vproc_standby_t handle);
#pragma GCC visibility pop
Modified: trunk/launchd/src/protocol_job.defs
===================================================================
--- trunk/launchd/src/protocol_job.defs 2008-03-27 01:40:55 UTC (rev 23573)
+++ trunk/launchd/src/protocol_job.defs 2008-03-27 21:18:33 UTC (rev 23574)
@@ -95,7 +95,9 @@
__requestor_port: mach_port_t;
out __subset_port : mach_port_make_send_t);
-skip; /* create_service prior to 10.6 */
+routine setup_shmem(
+ __bs_port : job_t;
+ out __shmem_port : mach_port_move_send_t);
routine take_subset(
__bs_port : job_t;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.macosforge.org/pipermail/launchd-changes/attachments/20080327/dbfcd375/attachment-0001.html
More information about the launchd-changes
mailing list