[launchd-changes] [23776] trunk/launchd/src
source_changes at macosforge.org
source_changes at macosforge.org
Fri Jan 9 16:40:56 PST 2009
Revision: 23776
http://trac.macosforge.org/projects/launchd/changeset/23776
Author: dsorresso at apple.com
Date: 2009-01-09 16:40:56 -0800 (Fri, 09 Jan 2009)
Log Message:
-----------
<rdar://problem/6046664> TASK: flatten per-user bootstrap namespaces
<rdar://problem/6241360> Instruments requires SPI for setting environment variables of launchd daemons
Embedded changes.
Modified Paths:
--------------
trunk/launchd/src/launch_priv.h
trunk/launchd/src/launchctl.c
trunk/launchd/src/launchd.c
trunk/launchd/src/launchd_core_logic.c
trunk/launchd/src/launchd_core_logic.h
trunk/launchd/src/launchd_runtime.c
trunk/launchd/src/launchd_unix_ipc.c
trunk/launchd/src/libvproc.c
trunk/launchd/src/protocol_vproc.defs
trunk/launchd/src/vproc.h
trunk/launchd/src/vproc_priv.h
Modified: trunk/launchd/src/launch_priv.h
===================================================================
--- trunk/launchd/src/launch_priv.h 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launch_priv.h 2009-01-10 00:40:56 UTC (rev 23776)
@@ -38,7 +38,8 @@
#define LAUNCH_KEY_SETRESOURCELIMITS "SetResourceLimits"
#define LAUNCH_KEY_GETRUSAGESELF "GetResourceUsageSelf"
#define LAUNCH_KEY_GETRUSAGECHILDREN "GetResourceUsageChildren"
-
+#define LAUNCH_KEY_SETPRIORITYLIST "SetPriorityList"
+
#define LAUNCHD_SOCKET_ENV "LAUNCHD_SOCKET"
#define LAUNCHD_SOCK_PREFIX _PATH_VARTMP "launchd"
#define LAUNCHD_TRUSTED_FD_ENV "__LAUNCHD_FD"
@@ -46,12 +47,17 @@
#define LAUNCH_KEY_BATCHCONTROL "BatchControl"
#define LAUNCH_KEY_BATCHQUERY "BatchQuery"
#define LAUNCHD_DO_APPLE_INTERNAL_LOGGING "__DoAppleInternalLogging__"
-
+
+#define LAUNCH_KEY_JETSAMLABEL "JetsamLabel"
+#define LAUNCH_KEY_JETSAMFRONTMOST "JetsamFrontmost"
+#define LAUNCH_KEY_JETSAMPRIORITY "JetsamPriority"
+
#define LAUNCH_JOBKEY_TRANSACTIONCOUNT "TransactionCount"
#define LAUNCH_JOBKEY_QUARANTINEDATA "QuarantineData"
#define LAUNCH_JOBKEY_SANDBOXPROFILE "SandboxProfile"
#define LAUNCH_JOBKEY_SANDBOXFLAGS "SandboxFlags"
#define LAUNCH_JOBKEY_SANDBOX_NAMED "Named"
+#define LAUNCH_JOBKEY_JETSAMPRIORITY "JetsamPriority"
#define LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL "EnterKernelDebuggerBeforeKill"
#define LAUNCH_JOBKEY_PERJOBMACHSERVICES "PerJobMachServices"
Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launchctl.c 2009-01-10 00:40:56 UTC (rev 23776)
@@ -181,6 +181,7 @@
static int setenv_cmd(int argc, char *const argv[]);
static int unsetenv_cmd(int argc, char *const argv[]);
static int getenv_and_export_cmd(int argc, char *const argv[]);
+static int wait4debugger_cmd(int argc, char *const argv[]);
static int limit_cmd(int argc, char *const argv[]);
static int stdio_cmd(int argc, char *const argv[]);
@@ -216,6 +217,7 @@
{ "unsetenv", unsetenv_cmd, "Unset an environmental variable in launchd" },
{ "getenv", getenv_and_export_cmd, "Get an environmental variable from launchd" },
{ "export", getenv_and_export_cmd, "Export shell settings from launchd" },
+ { "debug", wait4debugger_cmd, "Set the WaitForDebugger flag for the target job to true." },
{ "limit", limit_cmd, "View and adjust launchd resource limits" },
{ "stdout", stdio_cmd, "Redirect launchd's standard out to the given path" },
{ "stderr", stdio_cmd, "Redirect launchd's standard error to the given path" },
@@ -527,6 +529,37 @@
return 0;
}
+int
+wait4debugger_cmd(int argc, char * const argv[])
+{
+ if( argc != 3 ) {
+ fprintf(stderr, "%s usage: debug <label> <value>\n", argv[0]);
+ return 1;
+ }
+
+ int result = 1;
+ int64_t inval = 0;
+ if( strncmp(argv[2], "true", sizeof("true")) == 0 ) {
+ inval = 1;
+ } else if( strncmp(argv[2], "false", sizeof("false")) != 0 ) {
+ inval = atoi(argv[2]);
+ inval &= 1;
+ }
+
+ vproc_t vp = vprocmgr_lookup_vproc(argv[1]);
+ if( vp ) {
+ vproc_err_t verr = vproc_swap_integer(vp, VPROC_GSK_WAITFORDEBUGGER, &inval, NULL);
+ if( verr ) {
+ fprintf(stderr, "Failed to set WaitForDebugger flag on %s.\n", argv[1]);
+ } else {
+ result = 0;
+ }
+ vproc_release(vp);
+ }
+
+ return result;
+}
+
void
unloadjob(launch_data_t job)
{
Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launchd.c 2009-01-10 00:40:56 UTC (rev 23776)
@@ -193,6 +193,8 @@
if( stat("/var/db/.launchd_flat_per_user_namespace", &sb) == 0 ) {
runtime_syslog(LOG_NOTICE | LOG_CONSOLE, "Flat per-user Mach namespaces enabled.");
}
+ /* We just wanted to print status about the per-user namespace. PID 1 doesn't have a flat namespace. */
+ g_flat_mach_namespace = false;
}
monitor_networking_state();
Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launchd_core_logic.c 2009-01-10 00:40:56 UTC (rev 23776)
@@ -82,7 +82,21 @@
#if HAVE_QUARANTINE
#include <quarantine.h>
#endif
+#if TARGET_OS_EMBEDDED
+#include <sys/kern_memorystatus.h>
+#else
+/* To make my life easier. */
+typedef struct jetsam_priority_entry {
+ pid_t pid;
+ uint32_t flags;
+} jetsam_priority_entry_t;
+enum {
+ kJetsamFlagsFrontmost = (1 << 0),
+ kJetsamFlagsKilled = (1 << 1)
+};
+#endif
+
#include "launch.h"
#include "launch_priv.h"
#include "launch_internal.h"
@@ -110,10 +124,11 @@
* If the job hasn't exited in the given number of seconds after sending
* it a SIGTERM, SIGKILL it. Can be overriden in the job plist.
*/
-#define LAUNCHD_MIN_JOB_RUN_TIME 10
-#define LAUNCHD_SAMPLE_TIMEOUT 1
-#define LAUNCHD_DEFAULT_EXIT_TIMEOUT 20
-#define LAUNCHD_SIGKILL_TIMER 5
+#define LAUNCHD_MIN_JOB_RUN_TIME 10
+#define LAUNCHD_SAMPLE_TIMEOUT 1
+#define LAUNCHD_DEFAULT_EXIT_TIMEOUT 20
+#define LAUNCHD_SIGKILL_TIMER 5
+#define LAUNCHD_JETSAM_PRIORITY_UNSET 0xdead1eebabell
#define SHUTDOWN_LOG_DIR "/var/log/shutdown"
@@ -230,6 +245,7 @@
struct envitem {
SLIST_ENTRY(envitem) sle;
+ bool one_shot;
char *value;
union {
const char key[0];
@@ -237,9 +253,10 @@
};
};
-static bool envitem_new(job_t j, const char *k, const char *v, bool global);
+static bool envitem_new(job_t j, const char *k, const char *v, bool global, bool one_shot);
static void envitem_delete(job_t j, struct envitem *ei, bool global);
static void envitem_setup(launch_data_t obj, const char *key, void *context);
+static void envitem_setup_one_shot(launch_data_t obj, const char *key, void *context);
struct limititem {
SLIST_ENTRY(limititem) sle;
@@ -306,6 +323,7 @@
SLIST_ENTRY(jobmgr_s) sle;
SLIST_HEAD(, jobmgr_s) submgrs;
LIST_HEAD(, job_s) jobs;
+ LIST_HEAD(, job_s) jetsam_jobs;
LIST_HEAD(, job_s) active_jobs[ACTIVE_JOB_HASH_SIZE];
LIST_HEAD(, machservice) ms_hash[MACHSERVICE_HASH_SIZE];
LIST_HEAD(, job_s) global_env_jobs;
@@ -317,6 +335,7 @@
unsigned int global_on_demand_cnt;
unsigned int hopefully_first_cnt;
unsigned int normal_active_cnt;
+ unsigned int jetsam_jobs_cnt;
unsigned int sent_stop_to_normal_jobs :1,
sent_stop_to_hopefully_last_jobs:1,
shutting_down :1,
@@ -364,8 +383,9 @@
#define AUTO_PICK_LEGACY_LABEL (const char *)(~0)
struct job_s {
- kq_callback kqjob_callback; /* MUST be first element of this structure for benefit of launchd's run loop. */
- LIST_ENTRY(job_s) sle;
+ kq_callback kqjob_callback; /* MUST be first element of this structure for benefit of launchd's run loop. */
+ LIST_ENTRY(job_s) sle;
+ LIST_ENTRY(job_s) jetsam_sle;
LIST_ENTRY(job_s) pid_hash_sle;
LIST_ENTRY(job_s) label_hash_sle;
LIST_ENTRY(job_s) global_env_sle;
@@ -384,7 +404,7 @@
cpu_type_t *j_binpref;
size_t j_binpref_cnt;
mach_port_t j_port;
- mach_port_t wait_reply_port; /* we probably should switch to a list of waiters */
+ mach_port_t wait_reply_port; /* we probably should switch to a list of waiters */
uid_t mach_uid;
jobmgr_t mgr;
size_t argc;
@@ -416,6 +436,7 @@
int log_redirect_fd;
int nice;
int stdout_err_fd;
+ long long jetsam_priority;
uint32_t timeout;
uint32_t exit_timeout;
uint64_t sent_signal_time;
@@ -449,6 +470,7 @@
start_pending :1, /* an event fired and the job should start, but not necessarily right away */
globargv :1, /* man launchd.plist --> EnableGlobbing */
wait4debugger :1, /* man launchd.plist --> WaitForDebugger */
+ wait4debugger_oneshot :1, /* One-shot WaitForDebugger. */
internal_exc_handler :1, /* MachExceptionHandler == true */
stall_before_exec :1, /* a hack to support an option of spawn_via_launchd() */
only_once :1, /* man launchd.plist --> LaunchOnlyOnce. Note: 5465184 Rename this to "HopefullyNeverExits" */
@@ -476,7 +498,8 @@
reap_after_sample :1, /* The job exited before sample did, so we should reap it after sample is done. */
nosy :1, /* The job has an OtherJobEnabled KeepAlive criterion. */
crashed :1, /* The job is the default Mach exception handler, and it crashed. */
- reaped :1; /* We've received NOTE_EXIT for the job. */
+ reaped :1, /* We've received NOTE_EXIT for the job. */
+ jetsam_frontmost :1; /* The job is considered "frontmost" by Jetsam. */
mode_t mask;
pid_t sample_pid;
const char label[0];
@@ -571,6 +594,11 @@
static void do_unmounts(void);
void eliminate_double_reboot(void);
+/* For Jetsam. */
+static void jetsam_priority_from_job(job_t j, bool front, jetsam_priority_entry_t *jp);
+static int job_cmp(const job_t *lhs, const job_t *rhs);
+int launchd_set_jetsam_priorities(launch_data_t priorities);
+
/* file local globals */
static size_t total_children;
static size_t total_anon_children;
@@ -1175,9 +1203,15 @@
/* Not a big deal if this fails. It means that the timer's already been freed. */
kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
}
-
+
+ if( j->jetsam_priority != LAUNCHD_JETSAM_PRIORITY_UNSET ) {
+ LIST_REMOVE(j, jetsam_sle);
+ j->mgr->jetsam_jobs_cnt--;
+ }
+
kevent_mod((uintptr_t)j, EVFILT_TIMER, EV_DELETE, 0, 0, NULL);
-
+ kevent_mod((uintptr_t)j, EVFILT_PROC, EV_DELETE, 0, 0, NULL);
+
LIST_REMOVE(j, sle);
LIST_REMOVE(j, label_hash_sle);
@@ -1497,7 +1531,8 @@
j->currently_ignored = true;
j->ondemand = true;
j->checkedin = true;
-
+ j->jetsam_priority = LAUNCHD_JETSAM_PRIORITY_UNSET;
+
if (prog) {
j->prog = strdup(prog);
if (!job_assumes(j, j->prog != NULL)) {
@@ -1836,6 +1871,15 @@
}
}
break;
+ case 'j':
+ case 'J':
+ if( strcasecmp(key, LAUNCH_JOBKEY_JETSAMPRIORITY) == 0 ) {
+ job_log(j, LOG_DEBUG, "Importing job with priority: %lld", value);
+ j->jetsam_priority = (typeof(j->jetsam_priority))value;
+ LIST_INSERT_HEAD(&j->mgr->jetsam_jobs, j, jetsam_sle);
+ j->mgr->jetsam_jobs_cnt++;
+ }
+ break;
case 'n':
case 'N':
if (strcasecmp(key, LAUNCH_JOBKEY_NICE) == 0) {
@@ -2345,7 +2389,6 @@
struct ldcred *ldc = runtime_get_caller_creds();
job_t jr;
-
jr = job_mig_intran2(root_jobmgr, p, ldc->pid);
if (!jobmgr_assumes(root_jobmgr, jr != NULL)) {
@@ -2487,6 +2530,8 @@
job_mig_swap_integer(j, VPROC_GSK_WEIRD_BOOTSTRAP, 0, 0, &junk);
}
+ j->wait4debugger_oneshot = false;
+
if (j->log_redirect_fd && !j->legacy_LS_job) {
job_log_stdouterr(j); /* one last chance */
@@ -2633,6 +2678,13 @@
}
}
+ struct envitem *ei = NULL, *et = NULL;
+ SLIST_FOREACH_SAFE( ei, &j->env, sle, et ) {
+ if( ei->one_shot ) {
+ SLIST_REMOVE(&j->env, ei, envitem, sle);
+ }
+ }
+
if (j->hopefully_exits_first) {
j->mgr->hopefully_first_cnt--;
} else if (!j->anonymous && !j->hopefully_exits_last) {
@@ -3487,7 +3539,7 @@
argv++;
}
- if (unlikely(j->wait4debugger)) {
+ if (unlikely(j->wait4debugger || j->wait4debugger_oneshot)) {
job_log(j, LOG_WARNING, "Spawned and waiting for the debugger to attach before continuing...");
spflags |= POSIX_SPAWN_START_SUSPENDED;
}
@@ -4624,7 +4676,7 @@
}
bool
-envitem_new(job_t j, const char *k, const char *v, bool global)
+envitem_new(job_t j, const char *k, const char *v, bool global, bool one_shot)
{
struct envitem *ei = calloc(1, sizeof(struct envitem) + strlen(k) + 1 + strlen(v) + 1);
@@ -4635,6 +4687,7 @@
strcpy(ei->key_init, k);
ei->value = ei->key_init + strlen(k) + 1;
strcpy(ei->value, v);
+ ei->one_shot = one_shot;
if (global) {
if (SLIST_EMPTY(&j->global_env)) {
@@ -4675,12 +4728,28 @@
}
if( strncmp(LAUNCHD_TRUSTED_FD_ENV, key, sizeof(LAUNCHD_TRUSTED_FD_ENV) - 1) != 0 ) {
- envitem_new(j, key, launch_data_get_string(obj), j->importing_global_env);
+ envitem_new(j, key, launch_data_get_string(obj), j->importing_global_env, false);
} else {
job_log(j, LOG_WARNING, "Ignoring reserved environmental variable: %s", key);
}
}
+void
+envitem_setup_one_shot(launch_data_t obj, const char *key, void *context)
+{
+ job_t j = context;
+
+ if (launch_data_get_type(obj) != LAUNCH_DATA_STRING) {
+ return;
+ }
+
+ if( strncmp(LAUNCHD_TRUSTED_FD_ENV, key, sizeof(LAUNCHD_TRUSTED_FD_ENV) - 1) != 0 ) {
+ envitem_new(j, key, launch_data_get_string(obj), j->importing_global_env, true);
+ } else {
+ job_log(j, LOG_WARNING, "Ignoring reserved environmental variable: %s", key);
+ }
+}
+
bool
limititem_update(job_t j, int w, rlim_t r)
{
@@ -5544,7 +5613,7 @@
/* <rdar://problem/5042202> launchd-201: can't ssh in with AFP OD account (hangs) */
snprintf(buf, sizeof(buf), "0x%X:0:0", getuid());
- envitem_new(bootstrapper, "__CF_USER_TEXT_ENCODING", buf, false);
+ envitem_new(bootstrapper, "__CF_USER_TEXT_ENCODING", buf, false, false);
bootstrapper->weird_bootstrap = true;
jobmgr_assumes(jm, job_setup_machport(bootstrapper));
} else if( bootstrapper && strncmp(session_type, VPROCMGR_SESSION_SYSTEM, sizeof(VPROCMGR_SESSION_SYSTEM)) == 0 ) {
@@ -6423,7 +6492,7 @@
vm_offset_t *outval, mach_msg_type_number_t *outvalCnt)
{
const char *action;
- launch_data_t input_obj, output_obj;
+ launch_data_t input_obj = NULL, output_obj = NULL;
size_t data_offset = 0;
size_t packed_size;
struct ldcred *ldc = runtime_get_caller_creds();
@@ -6495,8 +6564,13 @@
}
if (invalCnt) switch (inkey) {
- case VPROC_GSK_ENVIRONMENT:
-
+ case VPROC_GSK_ENVIRONMENT:
+ if( launch_data_get_type(input_obj) == LAUNCH_DATA_DICTIONARY ) {
+ if( j->p ) {
+ job_log(j, LOG_NOTICE, "Setting environment for a currently active job. This environment will take effect on the next invocation of the job.");
+ }
+ launch_data_dict_iterate(input_obj, envitem_setup_one_shot, j);
+ }
break;
case 0:
break;
@@ -6587,6 +6661,9 @@
job_log(j, LOG_DEBUG, "Reading transaction model status.");
*outval = j->kill_via_shmem;
break;
+ case VPROC_GSK_WAITFORDEBUGGER:
+ *outval = j->wait4debugger;
+ break;
case 0:
*outval = 0;
break;
@@ -6660,6 +6737,7 @@
j->kill_via_shmem = (bool)inval;
job_log(j, LOG_DEBUG, "j->kill_via_shmem = %s", j->kill_via_shmem ? "true" : "false");
}
+ break;
case VPROC_GSK_WEIRD_BOOTSTRAP:
if( job_assumes(j, j->weird_bootstrap) ) {
job_log(j, LOG_DEBUG, "Unsetting weird bootstrap.");
@@ -6673,6 +6751,10 @@
job_assumes(j, runtime_add_mport(j->mgr->jm_port, protocol_vproc_server, mxmsgsz) == KERN_SUCCESS);
j->weird_bootstrap = false;
}
+ break;
+ case VPROC_GSK_WAITFORDEBUGGER:
+ j->wait4debugger_oneshot = inval;
+ break;
case 0:
break;
default:
@@ -7349,6 +7431,31 @@
return BOOTSTRAP_SUCCESS;
}
+kern_return_t
+job_mig_port_for_label(job_t j __attribute__((unused)), name_t label, mach_port_t *mp)
+{
+ struct ldcred *ldc = runtime_get_caller_creds();
+ kern_return_t kr = BOOTSTRAP_NOT_PRIVILEGED;
+
+ mach_port_t _mp = MACH_PORT_NULL;
+ if( ldc->euid == 0 || ldc->euid == geteuid() ) {
+ job_t target_j = job_find(label);
+ if( jobmgr_assumes(root_jobmgr, target_j != NULL) ) {
+ if( target_j->j_port == MACH_PORT_NULL ) {
+ job_assumes(target_j, job_setup_machport(target_j) == true);
+ }
+
+ _mp = target_j->j_port;
+ kr = _mp != MACH_PORT_NULL ? BOOTSTRAP_SUCCESS : BOOTSTRAP_NO_MEMORY;
+ } else {
+ kr = BOOTSTRAP_NO_MEMORY;
+ }
+ }
+
+ *mp = _mp;
+ return kr;
+}
+
jobmgr_t
jobmgr_find_by_name(jobmgr_t jm, const char *where)
{
@@ -8189,3 +8296,120 @@
}
}
}
+
+static void
+jetsam_priority_from_job(job_t j, bool front, jetsam_priority_entry_t *jp)
+{
+ jp->pid = j->p;
+ jp->flags |= front ? kJetsamFlagsFrontmost : 0;
+}
+
+static int
+job_cmp(const job_t *lhs, const job_t *rhs)
+{
+ job_t _lhs = *lhs;
+ job_t _rhs = *rhs;
+ /* Sort in descending order. (Priority correlates to the soonishness with which you will be killed.) */
+ if( _lhs->jetsam_priority > _rhs->jetsam_priority ) {
+ return -1;
+ } else if( _lhs->jetsam_priority < _rhs->jetsam_priority ) {
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+launchd_set_jetsam_priorities(launch_data_t priorities)
+{
+ if( !launchd_assumes(launch_data_get_type(priorities) == LAUNCH_DATA_ARRAY) ) {
+ return EINVAL;
+ }
+
+ jobmgr_t jm = NULL;
+#if !TARGET_OS_EMBEDDED
+ /* For testing. */
+ jm = jobmgr_find_by_name(root_jobmgr, VPROCMGR_SESSION_AQUA);
+ if( !launchd_assumes(jm != NULL) ) {
+ return EINVAL;
+ }
+#else
+ /* Since this is for embedded, we can assume that the root job manager holds the Jetsam jobs. */
+ jm = root_jobmgr;
+#endif
+
+ size_t npris = launch_data_array_get_count(priorities);
+
+ job_t ji = NULL;
+ size_t i = 0;
+ for( i = 0; i < npris; i++ ) {
+ launch_data_t ldi = launch_data_array_get_index(priorities, i);
+ if( !launchd_assumes(launch_data_get_type(ldi) == LAUNCH_DATA_DICTIONARY) ) {
+ continue;
+ }
+
+ launch_data_t label = NULL;
+ if( !launchd_assumes(label = launch_data_dict_lookup(ldi, LAUNCH_KEY_JETSAMLABEL)) ) {
+ continue;
+ }
+ const char *_label = launch_data_get_string(label);
+
+ ji = job_find(_label);
+ if( !launchd_assumes(ji != NULL) ) {
+ continue;
+ }
+
+ launch_data_t pri;
+ long long _pri = 0;
+ if( !launchd_assumes(pri = launch_data_dict_lookup(ldi, LAUNCH_KEY_JETSAMPRIORITY)) ) {
+ continue;
+ }
+ _pri = launch_data_get_integer(pri);
+
+ if( ji->jetsam_priority == LAUNCHD_JETSAM_PRIORITY_UNSET ) {
+ LIST_INSERT_HEAD(&ji->mgr->jetsam_jobs, ji, jetsam_sle);
+ ji->mgr->jetsam_jobs_cnt++;
+ }
+ ji->jetsam_priority = _pri;
+
+ launch_data_t frontmost = NULL;
+ if( !(frontmost = launch_data_dict_lookup(ldi, LAUNCH_KEY_JETSAMFRONTMOST)) ) {
+ ji->jetsam_frontmost = false;
+ continue;
+ }
+ ji->jetsam_frontmost = launch_data_get_bool(frontmost);
+ }
+
+ i = 0;
+ job_t *jobs = (job_t *)calloc(jm->jetsam_jobs_cnt, sizeof(job_t));
+ LIST_FOREACH( ji, &jm->jetsam_jobs, jetsam_sle ) {
+ if( ji->p ) {
+ jobs[i] = ji;
+ i++;
+ }
+ }
+ size_t totalpris = i;
+
+ int result = EINVAL;
+ if( launchd_assumes(totalpris > 0) ) {
+ qsort((void *)jobs, totalpris, sizeof(job_t), (int (*)(const void *, const void *))job_cmp);
+
+ jetsam_priority_entry_t *jpris = (jetsam_priority_entry_t *)calloc(totalpris, sizeof(jetsam_priority_entry_t));
+ if( !launchd_assumes(jpris != NULL) ) {
+ result = ENOMEM;
+ } else {
+ for( i = 0; i < totalpris; i++ ) {
+ jetsam_priority_from_job(jobs[i], jobs[i]->jetsam_frontmost, &jpris[i]);
+ }
+
+ int _result = 0;
+ launchd_assumes((_result = sysctlbyname("kern.memorystatus_priority_list", NULL, NULL, &jpris[0], totalpris * sizeof(jetsam_priority_entry_t))) != -1);
+ result = _result != 0 ? errno : 0;
+
+ free(jpris);
+ }
+ }
+ free(jobs);
+
+ return result;
+}
Modified: trunk/launchd/src/launchd_core_logic.h
===================================================================
--- trunk/launchd/src/launchd_core_logic.h 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launchd_core_logic.h 2009-01-10 00:40:56 UTC (rev 23776)
@@ -56,4 +56,6 @@
void job_log(job_t j, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4)));
void job_set_pid_crashed(pid_t p);
+int launchd_set_jetsam_priorities(launch_data_t priorities);
+
#endif
Modified: trunk/launchd/src/launchd_runtime.c
===================================================================
--- trunk/launchd/src/launchd_runtime.c 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launchd_runtime.c 2009-01-10 00:40:56 UTC (rev 23776)
@@ -131,7 +131,7 @@
bool do_apple_internal_logging;
bool low_level_debug;
bool g_force_old_kill_path = false;
-bool g_flat_mach_namespace = false;
+bool g_flat_mach_namespace = true;
mach_port_t
runtime_get_kernel_port(void)
@@ -1743,7 +1743,7 @@
g_force_old_kill_path = true;
}
- if( !pid1_magic && stat("/var/db/.launchd_flat_per_user_namespace", &sb) == 0 ) {
- g_flat_mach_namespace = true;
+ if( !pid1_magic && stat("/var/db/.launchd_no_flat_per_user_namespace", &sb) == 0 ) {
+ g_flat_mach_namespace = false;
}
}
Modified: trunk/launchd/src/launchd_unix_ipc.c
===================================================================
--- trunk/launchd/src/launchd_unix_ipc.c 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/launchd_unix_ipc.c 2009-01-10 00:40:56 UTC (rev 23776)
@@ -415,6 +415,8 @@
resp = job_export(j);
ipc_revoke_fds(resp);
}
+ } else if( !strcmp(cmd, LAUNCH_KEY_SETPRIORITYLIST) ) {
+ resp = launch_data_new_errno(launchd_set_jetsam_priorities(data));
}
rmc->resp = resp;
Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/libvproc.c 2009-01-10 00:40:56 UTC (rev 23776)
@@ -34,6 +34,8 @@
#include <pthread.h>
#include <signal.h>
#include <assert.h>
+#include <libkern/OSAtomic.h>
+
#if HAVE_QUARANTINE
#include <quarantine.h>
#endif
@@ -59,6 +61,55 @@
static pthread_once_t shmem_inited = PTHREAD_ONCE_INIT;
static uint64_t s_cached_transactions_enabled = 0;
+struct vproc_s {
+ int32_t refcount;
+ mach_port_t j_port;
+};
+
+vproc_t vprocmgr_lookup_vproc(const char *label)
+{
+ struct vproc_s *vp = NULL;
+
+ mach_port_t mp = MACH_PORT_NULL;
+ kern_return_t kr = vproc_mig_port_for_label(bootstrap_port, (char *)label, &mp);
+ if( kr == BOOTSTRAP_SUCCESS ) {
+ vp = (struct vproc_s *)calloc(1, sizeof(struct vproc_s));
+ if( vp ) {
+ vp->refcount = 1;
+ mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_SEND, 1);
+ vp->j_port = mp;
+ }
+ mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_SEND, -1);
+ }
+
+ return vp;
+}
+
+vproc_t vproc_retain(vproc_t vp)
+{
+ int32_t orig = OSAtomicAdd32(1, &vp->refcount) - 1;
+ if( orig <= 0 ) {
+ /* We've gone from 0 to 1, which means that this object was due to be freed. */
+ __crashreporter_info__ = "Under-retain / over-release of vproc_t.";
+ abort();
+ }
+
+ return vp;
+}
+
+void vproc_release(vproc_t vp)
+{
+ int32_t newval = OSAtomicAdd32(-1, &vp->refcount);
+ if( newval < 0 ) {
+ /* We're in negative numbers, which is bad. */
+ __crashreporter_info__ = "Over-release of vproc_t.";
+ abort();
+ } else if( newval == 0 ) {
+ mach_port_deallocate(mach_task_self(), vp->j_port);
+ free(vp);
+ }
+}
+
static void
vproc_shmem_init(void)
{
@@ -746,7 +797,7 @@
}
vproc_err_t
-vproc_swap_integer(vproc_t vp __attribute__((unused)), vproc_gsk_t key, int64_t *inval, int64_t *outval)
+vproc_swap_integer(vproc_t vp, vproc_gsk_t key, int64_t *inval, int64_t *outval)
{
static int64_t cached_is_managed = -1;
int64_t dummyval = 0;
@@ -785,7 +836,8 @@
break;
}
- if (vproc_mig_swap_integer(bootstrap_port, inval ? key : 0, outval ? key : 0, inval ? *inval : 0, outval ? outval : &dummyval) == 0) {
+ mach_port_t mp = vp ? vp->j_port : bootstrap_port;
+ if (vproc_mig_swap_integer(mp, inval ? key : 0, outval ? key : 0, inval ? *inval : 0, outval ? outval : &dummyval) == 0) {
switch (key) {
case VPROC_GSK_MGR_PID:
cached_pid = outval ? *outval : dummyval;
@@ -832,7 +884,7 @@
}
vproc_err_t
-vproc_swap_complex(vproc_t vp __attribute__((unused)), vproc_gsk_t key, launch_data_t inval, launch_data_t *outval)
+vproc_swap_complex(vproc_t vp, vproc_gsk_t key, launch_data_t inval, launch_data_t *outval)
{
size_t data_offset = 0, good_enough_size = 10*1024*1024;
mach_msg_type_number_t indata_cnt = 0, outdata_cnt;
@@ -853,7 +905,8 @@
indata = (vm_offset_t)buf;
}
- if (vproc_mig_swap_complex(bootstrap_port, inval ? key : 0, outval ? key : 0, indata, indata_cnt, &outdata, &outdata_cnt) != 0) {
+ mach_port_t mp = vp ? vp->j_port : bootstrap_port;
+ if (vproc_mig_swap_complex(mp, inval ? key : 0, outval ? key : 0, indata, indata_cnt, &outdata, &outdata_cnt) != 0) {
goto out;
}
Modified: trunk/launchd/src/protocol_vproc.defs
===================================================================
--- trunk/launchd/src/protocol_vproc.defs 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/protocol_vproc.defs 2009-01-10 00:40:56 UTC (rev 23776)
@@ -199,3 +199,7 @@
__pid : pid_t;
out __managed : boolean_t);
+routine port_for_label(
+ __bs_port : job_t;
+ __label : name_t;
+out __mp : mach_port_make_send_t);
Modified: trunk/launchd/src/vproc.h
===================================================================
--- trunk/launchd/src/vproc.h 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/vproc.h 2009-01-10 00:40:56 UTC (rev 23776)
@@ -34,7 +34,7 @@
typedef void * vproc_err_t;
-typedef void * vproc_t;
+typedef struct vproc_s * vproc_t;
typedef void * vprocmgr_t;
const char *vproc_strerror(vproc_err_t r);
Modified: trunk/launchd/src/vproc_priv.h
===================================================================
--- trunk/launchd/src/vproc_priv.h 2009-01-08 23:44:10 UTC (rev 23775)
+++ trunk/launchd/src/vproc_priv.h 2009-01-10 00:40:56 UTC (rev 23776)
@@ -59,12 +59,17 @@
VPROC_GSK_ABANDON_PROCESS_GROUP,
VPROC_GSK_TRANSACTIONS_ENABLED,
VPROC_GSK_WEIRD_BOOTSTRAP,
+ VPROC_GSK_WAITFORDEBUGGER,
} vproc_gsk_t;
typedef unsigned int vproc_flags_t;
/* For _vproc_kickstart_by_label() -- instructs launchd to kickstart the job to stall before exec(2). */
#define VPROCFLAG_STALL_JOB_EXEC 1 << 1
+vproc_t vprocmgr_lookup_vproc(const char *label);
+vproc_t vproc_retain(vproc_t vp);
+void vproc_release(vproc_t vp);
+
vproc_err_t vproc_swap_integer(vproc_t vp, vproc_gsk_t key, int64_t *inval, int64_t *outval);
vproc_err_t vproc_swap_complex(vproc_t vp, vproc_gsk_t key, launch_data_t inval, launch_data_t *outval);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20090109/6a474945/attachment-0001.html>
More information about the launchd-changes
mailing list