[launchd-changes] [23760] trunk
source_changes at macosforge.org
source_changes at macosforge.org
Wed Dec 10 20:42:32 PST 2008
Revision: 23760
http://trac.macosforge.org/projects/launchd/changeset/23760
Author: dsorresso at apple.com
Date: 2008-12-10 20:42:32 -0800 (Wed, 10 Dec 2008)
Log Message:
-----------
<rdar://problem/6263051> launchd should remove the BezelUI hack
<rdar://problem/6271234> QFA: Need to be able to install software at shutdown time to eliminate double reboot
<rdar://problem/6399100> launchd is killing stray processes at shutdown, but only when running Apple-internal?
<rdar://problem/6416724> launchd_libs should go to the heap if it can't allocate shared memory for Instant Off (for debugging purposes)
<rdar://problem/6423066> launchctl should have an option to output XML so that it can be integrated easily with scripts
<rdar://problem/6423070> launchctl should have an option to talk to the root launchd
<rdar://problem/6426061> launchctl should have "managerpid" and "manageruid" subcommands
<rdar://problem/6427956> SnowLeopard10A226: hang on attempt to restart
<rdar://problem/6010023> Repair critical directories, /private/tmp, /var/folders/, et al. at boot?
Embedded build fixes.
Modified Paths:
--------------
trunk/launchd/src/launchctl.c
trunk/launchd/src/launchd.c
trunk/launchd/src/launchd_core_logic.c
trunk/launchd/src/launchd_runtime.c
trunk/launchd/src/libbootstrap.c
trunk/launchd/src/liblaunch.c
trunk/launchd/src/libvproc.c
trunk/launchd/src/protocol_vproc.defs
trunk/launchd/src/vproc_priv.h
trunk/launchd.xcodeproj/project.pbxproj
Modified: trunk/launchd/src/launchctl.c
===================================================================
--- trunk/launchd/src/launchctl.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/launchctl.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -105,6 +105,9 @@
};
static void myCFDictionaryApplyFunction(const void *key, const void *value, void *context);
+static CFTypeRef CFTypeCreateFromLaunchData(launch_data_t obj);
+static CFArrayRef CFArrayCreateFromLaunchArray(launch_data_t arr);
+static CFDictionaryRef CFDictionaryCreateFromLaunchDictionary(launch_data_t dict);
static bool launch_data_array_append(launch_data_t a, launch_data_t o);
static void distill_jobs(launch_data_t);
static void distill_config_file(launch_data_t);
@@ -158,6 +161,7 @@
static bool job_disabled_logic(launch_data_t obj);
static void fix_bogus_file_metadata(void);
static void do_file_init(void) __attribute__((constructor));
+static void setup_system_context(void);
typedef enum {
BOOTCACHE_START = 1,
@@ -189,7 +193,8 @@
static int bslist_cmd(int argc, char *const argv[]);
static int _bstree_cmd(mach_port_t bsport, unsigned int depth);
static int bstree_cmd(int argc __attribute__((unused)), char * const argv[] __attribute__((unused)));
-
+static int managerpid_cmd(int argc __attribute__((unused)), char * const argv[] __attribute__((unused)));
+static int manageruid_cmd(int argc __attribute__((unused)), char * const argv[] __attribute__((unused)));
static int exit_cmd(int argc, char *const argv[]) __attribute__((noreturn));
static int help_cmd(int argc, char *const argv[]);
@@ -198,39 +203,43 @@
int (*func)(int argc, char *const argv[]);
const char *desc;
} cmds[] = {
- { "load", load_and_unload_cmd, "Load configuration files and/or directories" },
- { "unload", load_and_unload_cmd, "Unload configuration files and/or directories" },
-// { "reload", reload_cmd, "Reload configuration files and/or directories" },
- { "start", start_stop_remove_cmd, "Start specified job" },
- { "stop", start_stop_remove_cmd, "Stop specified job" },
- { "submit", submit_cmd, "Submit a job from the command line" },
- { "remove", start_stop_remove_cmd, "Remove specified job" },
- { "bootstrap", bootstrap_cmd, "Bootstrap launchd" },
- { "list", list_cmd, "List jobs and information about jobs" },
- { "setenv", setenv_cmd, "Set an environmental variable in launchd" },
- { "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" },
- { "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" },
- { "shutdown", fyi_cmd, "Prepare for system shutdown" },
- { "singleuser", fyi_cmd, "Switch to single-user mode" },
- { "getrusage", getrusage_cmd, "Get resource usage statistics from launchd" },
- { "log", logupdate_cmd, "Adjust the logging level or mask of launchd" },
- { "umask", umask_cmd, "Change launchd's umask" },
- { "bsexec", bsexec_cmd, "Execute a process within a different Mach bootstrap subset" },
- { "bslist", bslist_cmd, "List Mach bootstrap services and optional servers" },
- { "bstree", bstree_cmd, "Show the entire Mach bootstrap tree. Requires root privileges." },
- { "exit", exit_cmd, "Exit the interactive invocation of launchctl" },
- { "quit", exit_cmd, "Quit the interactive invocation of launchctl" },
- { "help", help_cmd, "This help output" },
+ { "load", load_and_unload_cmd, "Load configuration files and/or directories" },
+ { "unload", load_and_unload_cmd, "Unload configuration files and/or directories" },
+// { "reload", reload_cmd, "Reload configuration files and/or directories" },
+ { "start", start_stop_remove_cmd, "Start specified job" },
+ { "stop", start_stop_remove_cmd, "Stop specified job" },
+ { "submit", submit_cmd, "Submit a job from the command line" },
+ { "remove", start_stop_remove_cmd, "Remove specified job" },
+ { "bootstrap", bootstrap_cmd, "Bootstrap launchd" },
+ { "list", list_cmd, "List jobs and information about jobs" },
+ { "setenv", setenv_cmd, "Set an environmental variable in launchd" },
+ { "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" },
+ { "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" },
+ { "shutdown", fyi_cmd, "Prepare for system shutdown" },
+ { "singleuser", fyi_cmd, "Switch to single-user mode" },
+ { "getrusage", getrusage_cmd, "Get resource usage statistics from launchd" },
+ { "log", logupdate_cmd, "Adjust the logging level or mask of launchd" },
+ { "umask", umask_cmd, "Change launchd's umask" },
+ { "bsexec", bsexec_cmd, "Execute a process within a different Mach bootstrap subset" },
+ { "bslist", bslist_cmd, "List Mach bootstrap services and optional servers" },
+ { "bstree", bstree_cmd, "Show the entire Mach bootstrap tree. Requires root privileges." },
+ { "managerpid", managerpid_cmd, "Print the PID of the launchd managing this Mach bootstrap." },
+ { "manageruid", manageruid_cmd, "Print the UID of the launchd managing this Mach bootstrap." },
+ { "exit", exit_cmd, "Exit the interactive invocation of launchctl" },
+ { "quit", exit_cmd, "Quit the interactive invocation of launchctl" },
+ { "help", help_cmd, "This help output" },
};
static bool istty;
static bool verbose;
static bool is_managed;
static bool do_apple_internal_magic;
+static bool system_context;
+static bool rootuser_context;
int
main(int argc, char *const argv[])
@@ -241,18 +250,10 @@
if (vproc_swap_integer(NULL, VPROC_GSK_IS_MANAGED, NULL, &is_managed_val) == NULL && is_managed_val) {
is_managed = true;
}
-
- if (getuid() == 0 && !is_managed) {
- mach_port_t root_bs = str2bsport("/");
- task_set_bootstrap_port(mach_task_self(), root_bs);
- mach_port_deallocate(mach_task_self(), bootstrap_port);
- bootstrap_port = root_bs;
- }
-
+
istty = isatty(STDIN_FILENO);
-
argc--, argv++;
-
+
if (argc > 0 && argv[0][0] == '-') {
char *flago;
@@ -261,6 +262,22 @@
case 'v':
verbose = true;
break;
+ case 'u':
+ if( argc > 1 ) {
+ if( strncmp(argv[1], "root", sizeof("root")) == 0 ) {
+ rootuser_context = true;
+ } else {
+ fprintf(stderr, "Unknown user: %s\n", argv[1]);
+ exit(EXIT_FAILURE);
+ }
+ argc--, argv++;
+ } else {
+ fprintf(stderr, "-u option requires an argument. Currently, only \"root\" is supported.\n");
+ }
+ break;
+ case '1':
+ system_context = true;
+ break;
default:
fprintf(stderr, "Unknown argument: '-%c'\n", *flago);
break;
@@ -269,6 +286,38 @@
argc--, argv++;
}
+ /* Running in the context of the root user's per-user launchd is only supported ... well
+ * in the root user's per-user context. I know it's confusing. I'm genuinely sorry.
+ */
+ if( rootuser_context ) {
+ int64_t manager_uid = -1, manager_pid = -1;
+ if( vproc_swap_integer(NULL, VPROC_GSK_MGR_UID, NULL, &manager_uid) == NULL ) {
+ if( vproc_swap_integer(NULL, VPROC_GSK_MGR_PID, NULL, &manager_pid) == NULL ) {
+ if( manager_uid || manager_uid == 1 ) {
+ fprintf(stderr, "Running in the root user's per-user context is not supported outside of the root user's bootstrap.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+ }
+ } else if( !(system_context || rootuser_context) ) {
+ /* Running in the system context is implied when we're running as root and not running as a bootstrapper. */
+ system_context = ( !is_managed && getuid() == 0 );
+ }
+
+ if( system_context ) {
+ if( getuid() == 0 ) {
+ setup_system_context();
+ } else {
+ fprintf(stderr, "You must be root to run in the system context.\n");
+ exit(EXIT_FAILURE);
+ }
+ } else if( rootuser_context ) {
+ if( getuid() != 0 ) {
+ fprintf(stderr, "You must be root to run in the root user context.\n");
+ exit(EXIT_FAILURE);
+ }
+ }
+
if (NULL == readline) {
fprintf(stderr, "missing library: readline\n");
exit(EXIT_FAILURE);
@@ -312,7 +361,7 @@
optind = 1;
optreset = 1;
-
+
for (i = 0; i < (sizeof cmds / sizeof cmds[0]); i++) {
if (!strcmp(cmds[i].name, argv[0])) {
return cmds[i].func(argc, argv);
@@ -1221,6 +1270,149 @@
}
}
+static inline Boolean __is_launch_data_t(launch_data_t obj)
+{
+ Boolean result = true;
+
+ switch( launch_data_get_type(obj) ) {
+ case LAUNCH_DATA_STRING : break;
+ case LAUNCH_DATA_INTEGER : break;
+ case LAUNCH_DATA_REAL : break;
+ case LAUNCH_DATA_BOOL : break;
+ case LAUNCH_DATA_ARRAY : break;
+ case LAUNCH_DATA_DICTIONARY : break;
+ case LAUNCH_DATA_FD : break;
+ case LAUNCH_DATA_MACHPORT : break;
+ default : result = false;
+ }
+
+ return result;
+}
+
+static void __launch_data_iterate(launch_data_t obj, const char *key, CFMutableDictionaryRef dict)
+{
+ if( obj && __is_launch_data_t(obj) ) {
+ CFStringRef cfKey = CFStringCreateWithCString(NULL, key, kCFStringEncodingUTF8);
+ CFTypeRef cfVal = CFTypeCreateFromLaunchData(obj);
+
+ if( cfVal ) {
+ CFDictionarySetValue(dict, cfKey, cfVal);
+ CFRelease(cfVal);
+ }
+ CFRelease(cfKey);
+ }
+}
+
+static CFTypeRef CFTypeCreateFromLaunchData(launch_data_t obj)
+{
+ CFTypeRef cfObj = NULL;
+
+ switch( launch_data_get_type(obj) ) {
+ case LAUNCH_DATA_STRING :
+ {
+ const char *str = launch_data_get_string(obj);
+ cfObj = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8);
+
+ break;
+ }
+ case LAUNCH_DATA_INTEGER :
+ {
+ long long integer = launch_data_get_integer(obj);
+ cfObj = CFNumberCreate(NULL, kCFNumberLongLongType, &integer);
+
+ break;
+ }
+ case LAUNCH_DATA_REAL :
+ {
+ double real = launch_data_get_real(obj);
+ cfObj = CFNumberCreate(NULL, kCFNumberDoubleType, &real);
+
+ break;
+ }
+ case LAUNCH_DATA_BOOL :
+ {
+ bool yesno = launch_data_get_bool(obj);
+ cfObj = yesno ? kCFBooleanTrue : kCFBooleanFalse;
+
+ break;
+ }
+ case LAUNCH_DATA_ARRAY :
+ {
+ cfObj = (CFTypeRef)CFArrayCreateFromLaunchArray(obj);
+
+ break;
+ }
+ case LAUNCH_DATA_DICTIONARY :
+ {
+ cfObj = (CFTypeRef)CFDictionaryCreateFromLaunchDictionary(obj);
+
+ break;
+ }
+ case LAUNCH_DATA_FD :
+ {
+ int fd = launch_data_get_fd(obj);
+ cfObj = CFNumberCreate(NULL, kCFNumberIntType, &fd);
+
+ break;
+ }
+ case LAUNCH_DATA_MACHPORT :
+ {
+ mach_port_t port = launch_data_get_machport(obj);
+ cfObj = CFNumberCreate(NULL, kCFNumberIntType, &port);
+
+ break;
+ }
+ default : break;
+ }
+
+ return cfObj;
+}
+
+#pragma mark CFArray
+CFArrayRef CFArrayCreateFromLaunchArray(launch_data_t arr)
+{
+ CFArrayRef result = NULL;
+ CFMutableArrayRef mutResult = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+
+ if( launch_data_get_type(arr) == LAUNCH_DATA_ARRAY ) {
+ unsigned int count = launch_data_array_get_count(arr);
+ unsigned int i = 0;
+
+ for( i = 0; i < count; i++ ) {
+ launch_data_t launch_obj = launch_data_array_get_index(arr, i);
+ CFTypeRef obj = CFTypeCreateFromLaunchData(launch_obj);
+
+ if( obj ) {
+ CFArrayAppendValue(mutResult, obj);
+ CFRelease(obj);
+ }
+ }
+
+ result = CFArrayCreateCopy(NULL, mutResult);
+
+ CFRelease(mutResult);
+ }
+
+ return result;
+}
+
+#pragma mark CFDictionary / CFPropertyList
+static CFDictionaryRef CFDictionaryCreateFromLaunchDictionary(launch_data_t dict)
+{
+ CFDictionaryRef result = NULL;
+
+ if( launch_data_get_type(dict) == LAUNCH_DATA_DICTIONARY ) {
+ CFMutableDictionaryRef mutResult = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ launch_data_dict_iterate(dict, (void (*)(launch_data_t, const char *, void *))__launch_data_iterate, mutResult);
+
+ result = CFDictionaryCreateCopy(NULL, mutResult);
+ CFRelease(mutResult);
+ }
+
+ return result;
+}
+
void
myCFDictionaryApplyFunction(const void *key, const void *value, void *context)
{
@@ -1484,6 +1676,26 @@
assumes(fwexec(rccleanup_tool, NULL) != -1);
}
+ if( path_check("/etc/rc.deferredinstall") ) {
+ int status = 0;
+ const char *deferredinstall_tool[] = { _PATH_BSHELL, "/etc/rc.deferredinstall", NULL };
+ if( assumes(fwexec(deferredinstall_tool, &status) != -1) ) {
+ if( WEXITSTATUS(status) == EXIT_SUCCESS ) {
+ if( do_apple_internal_magic ) {
+ fprintf(stdout, "Deferred install script completed successfully. Rebooting in 3 seconds...\n");
+ sleep(3);
+ }
+
+ assumes(remove(deferredinstall_tool[1]) != -1);
+ assumes(reboot(RB_AUTOBOOT) != -1);
+ exit(EXIT_FAILURE);
+ } else {
+ fprintf(stdout, "Deferred install script exited with status %i. Continuing boot and hoping it'll work...\n", WEXITSTATUS(status));
+ assumes(remove(deferredinstall_tool[1]) != -1);
+ }
+ }
+ }
+
empty_dir(_PATH_VARRUN, NULL);
empty_dir(_PATH_TMP, NULL);
remove(_PATH_NOLOGIN);
@@ -2094,39 +2306,68 @@
int
list_cmd(int argc, char *const argv[])
{
- launch_data_t resp, msg;
+ launch_data_t resp, msg = NULL;
int r = 0;
- if (argc > 2) {
- fprintf(stderr, "usage: %s list [label]\n", getprogname());
+ bool plist_output = false;
+ char *label = NULL;
+ if (argc > 3) {
+ fprintf(stderr, "usage: %s list [-x] [label]\n", getprogname());
return 1;
- } else if (argc == 2) {
+ } else if( argc >= 2 ) {
+ plist_output = ( strncmp(argv[1], "-x", sizeof("-x")) == 0 );
+ label = plist_output ? argv[2] : argv[1];
+ }
+
+ if( label ) {
msg = launch_data_alloc(LAUNCH_DATA_DICTIONARY);
- launch_data_dict_insert(msg, launch_data_new_string(argv[1]), LAUNCH_KEY_GETJOB);
- } else if (vproc_swap_complex(NULL, VPROC_GSK_ALLJOBS, NULL, &resp) == NULL) {
+ launch_data_dict_insert(msg, launch_data_new_string(label), LAUNCH_KEY_GETJOB);
+
+ resp = launch_msg(msg);
+ launch_data_free(msg);
+
+ if (resp == NULL) {
+ fprintf(stderr, "launch_msg(): %s\n", strerror(errno));
+ r = 1;
+ } else if (launch_data_get_type(resp) == LAUNCH_DATA_DICTIONARY) {
+ if( plist_output ) {
+ CFDictionaryRef respDict = CFDictionaryCreateFromLaunchDictionary(resp);
+ CFStringRef plistStr = NULL;
+ if( respDict ) {
+ CFDataRef plistData = CFPropertyListCreateXMLData(NULL, (CFPropertyListRef)respDict);
+ CFRelease(respDict);
+ if( plistData ) {
+ plistStr = CFStringCreateWithBytes(NULL, CFDataGetBytePtr(plistData), CFDataGetLength(plistData), kCFStringEncodingUTF8, false);
+ CFRelease(plistData);
+ } else {
+ r = 1;
+ }
+ } else {
+ r = 1;
+ }
+
+ if( plistStr ) {
+ CFShow(plistStr);
+ r = 0;
+ }
+ } else {
+ print_obj(resp, NULL, NULL);
+ r = 0;
+ }
+ } else {
+ fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]);
+ r = 1;
+ }
+
+ launch_data_free(resp);
+ } else if( vproc_swap_complex(NULL, VPROC_GSK_ALLJOBS, NULL, &resp) == NULL ) {
fprintf(stdout, "PID\tStatus\tLabel\n");
launch_data_dict_iterate(resp, print_jobs, NULL);
launch_data_free(resp);
- return 0;
- } else {
- return 1;
+
+ r = 0;
}
- resp = launch_msg(msg);
- launch_data_free(msg);
-
- if (resp == NULL) {
- fprintf(stderr, "launch_msg(): %s\n", strerror(errno));
- return 1;
- } else if (launch_data_get_type(resp) == LAUNCH_DATA_DICTIONARY) {
- print_obj(resp, NULL, NULL);
- } else {
- fprintf(stderr, "%s %s returned unknown response\n", getprogname(), argv[0]);
- r = 1;
- }
-
- launch_data_free(resp);
-
return r;
}
@@ -2473,6 +2714,24 @@
}
}
+void
+setup_system_context(void)
+{
+ if( geteuid() != 0 ) {
+ fprintf(stderr, "You must be the root user to perform this operation.\n");
+ return;
+ }
+
+ /* Use the system launchd's socket. */
+ setenv("__USE_SYSTEM_LAUNCHD", "1", 0);
+
+ /* Put ourselves in the system launchd's bootstrap. */
+ mach_port_t rootbs = str2bsport("/");
+ mach_port_deallocate(mach_task_self(), bootstrap_port);
+ task_set_bootstrap_port(mach_task_self(), rootbs);
+ bootstrap_port = rootbs;
+}
+
int
submit_cmd(int argc, char *const argv[])
{
@@ -2699,7 +2958,7 @@
return 1;
}
- #define bport_state(x) (((x) == BOOTSTRAP_STATUS_ACTIVE) ? "A" : ((x) == BOOTSTRAP_STATUS_ON_DEMAND) ? "D" : "I")
+#define bport_state(x) (((x) == BOOTSTRAP_STATUS_ACTIVE) ? "A" : ((x) == BOOTSTRAP_STATUS_ON_DEMAND) ? "D" : "I")
for (i = 0; i < service_cnt ; i++) {
fprintf(stdout, "%*s%-3s%s\n", depth, "", bport_state((service_actives[i])), service_names[i]);
@@ -2775,6 +3034,34 @@
return _bstree_cmd(str2bsport("/"), 4);
}
+int
+managerpid_cmd(int argc __attribute__((unused)), char * const argv[] __attribute__((unused)))
+{
+ int64_t manager_pid = 0;
+ vproc_err_t verr = vproc_swap_integer(NULL, VPROC_GSK_MGR_PID, NULL, (int64_t *)&manager_pid);
+ if( verr ) {
+ fprintf(stdout, "Unknown job manager!\n");
+ return 1;
+ }
+
+ fprintf(stdout, "%d\n", (pid_t)manager_pid);
+ return 0;
+}
+
+int
+manageruid_cmd(int argc __attribute__((unused)), char * const argv[] __attribute__((unused)))
+{
+ int64_t manager_uid = 0;
+ vproc_err_t verr = vproc_swap_integer(NULL, VPROC_GSK_MGR_UID, NULL, (int64_t *)&manager_uid);
+ if( verr ) {
+ fprintf(stdout, "Unknown job manager!\n");
+ return 1;
+ }
+
+ fprintf(stdout, "%lli\n", manager_uid);
+ return 0;
+}
+
bool
is_legacy_mach_job(launch_data_t obj)
{
@@ -2929,7 +3216,7 @@
goto out;
}
#endif
- fprintf(stderr, "Running fsck on the boot volume...\n");
+ fprintf(stdout, "Running fsck on the boot volume...\n");
if (fwexec(fsck_tool, NULL) != -1) {
goto out;
}
@@ -2939,7 +3226,7 @@
goto out;
}
- fprintf(stderr, "fsck failed!\n");
+ fprintf(stdout, "fsck failed!\n");
/* someday, we should keep booting read-only, but as of today, other sub-systems cannot handle that scenario */
assumes(reboot(RB_HALT) != -1);
@@ -2958,7 +3245,7 @@
#if TARGET_OS_EMBEDDED
if (path_check("/etc/fstab")) {
const char *mount_tool[] = { "mount", "-vat", "nonfs", NULL };
- assumes(fwexec(mount_tool, true) != -1);
+ assumes(fwexec(mount_tool, NULL) != -1);
} else
#endif
{
@@ -2977,10 +3264,12 @@
const gid_t group;
const mode_t needed_bits;
const mode_t bad_bits;
+ const bool create;
} f[] = {
- { "/sbin/launchd", 0, 0, S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, S_ISUID|S_ISGID|S_ISVTX|S_IWOTH },
- { _PATH_TMP, 0, 0, S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO, S_ISUID|S_ISGID },
- { _PATH_VARTMP, 0, 0, S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO, S_ISUID|S_ISGID },
+ { "/sbin/launchd", 0, 0, S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, S_ISUID|S_ISGID|S_ISVTX|S_IWOTH, false },
+ { _PATH_TMP, 0, 0, S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO, S_ISUID|S_ISGID, true },
+ { _PATH_VARTMP, 0, 0, S_ISTXT|S_IRWXU|S_IRWXG|S_IRWXO, S_ISUID|S_ISGID, true },
+ { "/var/folders", 0, 0, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH, S_ISUID | S_ISGID, true },
};
struct stat sb;
size_t i;
@@ -2992,7 +3281,16 @@
bool fix_id = false;
if (!assumes(stat(f[i].path, &sb) != -1)) {
- continue;
+ fprintf(stdout, "Crucial filesystem check: Path not present: %s. %s\n", f[i].path, f[i].create ? "Will create." : "");
+ if( f[i].create ) {
+ if( !assumes(mkdir(f[i].path, f[i].needed_bits) != -1) ) {
+ continue;
+ } else if( !assumes(stat(f[i].path, &sb) != -1) ) {
+ continue;
+ }
+ } else {
+ continue;
+ }
}
i_needed_bits = ~sb.st_mode & f[i].needed_bits;
Modified: trunk/launchd/src/launchd.c
===================================================================
--- trunk/launchd/src/launchd.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/launchd.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -200,9 +200,11 @@
if (pid1_magic) {
handle_pid1_crashes_separately();
} else {
+ #if !TARGET_OS_EMBEDDED
/* prime shared memory before the 'bootstrap_port' global is set to zero */
_vproc_transaction_begin();
_vproc_transaction_end();
+ #endif
}
if( pid1_magic ) {
@@ -213,7 +215,7 @@
}
jobmgr_init(sflag);
-
+
launchd_runtime_init2();
launchd_runtime();
Modified: trunk/launchd/src/launchd_core_logic.c
===================================================================
--- trunk/launchd/src/launchd_core_logic.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/launchd_core_logic.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -569,6 +569,7 @@
static void extract_rcsid_substr(const char *i, char *o, size_t osz);
static void do_first_per_user_launchd_hack(void);
static void do_unmounts(void);
+void eliminate_double_reboot(void);
/* file local globals */
static size_t total_children;
@@ -652,7 +653,8 @@
if (unlikely(!j->p || j->anonymous)) {
return;
}
-
+
+#if !TARGET_OS_EMBEDDED
if (j->kill_via_shmem && !g_force_old_kill_path) {
if (j->shmem) {
if (!j->sent_kill_via_shmem) {
@@ -668,6 +670,7 @@
} else if( j->kill_via_shmem ) {
job_log(j, LOG_DEBUG, "Stopping transactional job the old-fashioned way.");
}
+#endif
j->sent_signal_time = runtime_get_opaque_time();
@@ -1007,13 +1010,14 @@
runtime_del_weak_ref();
SLIST_REMOVE(&jm->parentmgr->submgrs, jm, jobmgr_s, sle);
} else if (pid1_magic) {
+ eliminate_double_reboot();
jobmgr_log(jm, LOG_DEBUG | LOG_CONSOLE, "About to call: sync()");
sync(); /* We're are going to rely on log timestamps to benchmark this call */
jobmgr_log(jm, LOG_DEBUG | LOG_CONSOLE, "Unmounting all filesystems except / and /dev");
do_unmounts();
launchd_log_vm_stats();
+ jobmgr_log(root_jobmgr, LOG_NOTICE | LOG_CONSOLE, "About to call: reboot(%s).", reboot_flags_to_C_names(jm->reboot_flags));
runtime_closelog();
- jobmgr_log(root_jobmgr, LOG_NOTICE | LOG_CONSOLE, "About to call: reboot(%s).", reboot_flags_to_C_names(jm->reboot_flags));
jobmgr_assumes(jm, reboot(jm->reboot_flags) != -1);
runtime_closelog();
} else {
@@ -2567,7 +2571,7 @@
td_sec = td / NSEC_PER_SEC;
td_usec = (td % NSEC_PER_SEC) / NSEC_PER_USEC;
- job_log(j, LOG_NOTICE, "Exited %llu.%06llu seconds after the first signal was sent", td_sec, td_usec);
+ job_log(j, LOG_DEBUG, "Exited %llu.%06llu seconds after the first signal was sent", td_sec, td_usec);
}
timeradd(&ru.ru_utime, &j->ru.ru_utime, &j->ru.ru_utime);
@@ -3097,6 +3101,9 @@
j->start_pending = true;
job_dispatch(j, false);
} else if (&j->exit_timeout == ident) {
+ if( !job_assumes(j, j->p != 0) ) {
+ return;
+ }
/*
* This block might be executed up to 3 times for a given (slow) job
* - once for the SAMPLE_TIMEOUT timer, at which point sampling is triggered
@@ -4351,7 +4358,7 @@
j->start_pending = true;
}
} else { /* Something happened to the parent directory. See if our target file appeared. */
- if( !invalidation_reason[0] ){
+ if( !invalidation_reason[0] ) {
job_assumes(j, runtime_close(si->fd) == 0);
si->fd = -1; /* this will get fixed in semaphoreitem_watch() */
semaphoreitem_watch(j, si);
@@ -5364,11 +5371,15 @@
continue;
}
- /* We might have some jobs hanging around that we've decided to shut down in spite of. If so, don't bother trying to kill them again. */
+ /* We might have some jobs hanging around that we've decided to shut down in spite of. */
job_t j = jobmgr_find_by_pid(jm, p_i, false);
if( !j || (j && j->anonymous) ) {
jobmgr_log(jm, LOG_WARNING, "Stray %s %s at shutdown: PID %u PPID %u PGID %u %s", z, j ? "anonymous job" : "process", p_i, pp_i, pg_i, n);
- jobmgr_kill_stray_child(jm, p_i);
+
+ /* <rdar://problem/6399100> Let the kernel clean up the stragglers. */
+ if( 0 ) {
+ jobmgr_kill_stray_child(jm, p_i);
+ }
}
}
@@ -5536,8 +5547,13 @@
envitem_new(bootstrapper, "__CF_USER_TEXT_ENCODING", buf, 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 ) {
+ if( jobmgr_assumes(jm, pid1_magic) ) {
+ /* Have our system bootstrapper print out to the console. */
+ bootstrapper->stdoutpath = _PATH_CONSOLE;
+ }
}
-
+
jm->session_initialized = true;
return bootstrapper;
@@ -5708,7 +5724,7 @@
}
if (ms->recv && job_assumes(j, !machservice_active(ms))) {
- job_log(j, LOG_NOTICE, "Closing receive right for %s", ms->name);
+ job_log(j, LOG_DEBUG, "Closing receive right for %s", ms->name);
job_assumes(j, launchd_mport_close_recv(ms->port) == KERN_SUCCESS);
}
@@ -5718,7 +5734,7 @@
the_exception_server = 0;
}
- job_log(j, LOG_NOTICE, "Mach service deleted%s: %s", port_died ? " (port died)" : "", ms->name);
+ job_log(j, LOG_DEBUG, "Mach service deleted%s: %s", port_died ? " (port died)" : "", ms->name);
if (ms->special_port_num) {
SLIST_REMOVE(&special_ports, ms, machservice, special_port_sle);
@@ -6350,14 +6366,14 @@
job_assumes(j, runtime_kill(otherj->p, SIGKILL) != -1);
return 0;
}
-
+ #if !TARGET_OS_EMBEDDED
if (__sync_bool_compare_and_swap(&j->shmem->vp_shmem_transaction_cnt, 0, -1)) {
j->shmem->vp_shmem_flags |= VPROC_SHMEM_EXITING;
j->sent_kill_via_shmem = true;
job_assumes(j, runtime_kill(otherj->p, SIGKILL) != -1);
return 0;
}
-
+ #endif
return BOOTSTRAP_NOT_PRIVILEGED;
} else if (otherj->p) {
job_assumes(j, runtime_kill(otherj->p, sig) != -1);
@@ -6643,7 +6659,7 @@
}
case VPROC_GSK_WEIRD_BOOTSTRAP:
if( job_assumes(j, j->weird_bootstrap) ) {
- job_log(j, LOG_NOTICE, "Unsetting weird bootstrap.");
+ job_log(j, LOG_DEBUG, "Unsetting weird bootstrap.");
mach_msg_size_t mxmsgsz = (typeof(mxmsgsz)) sizeof(union __RequestUnion__job_mig_protocol_vproc_subsystem);
@@ -7506,19 +7522,32 @@
}
kern_return_t
-job_mig_detach_from_console(job_t j, mach_port_t *new_bsport)
+job_mig_switch_to_session(job_t j, mach_port_t requestor_port, name_t session_name, mach_port_t *new_bsport)
{
- if( j->mgr == root_jobmgr ) {
+ job_log(j, LOG_NOTICE, "Job wants to move to %s session.", session_name);
+
+ if( !job_assumes(j, pid1_magic == false) ) {
+ job_log(j, LOG_WARNING, "Switching sessions is not allowed in the system Mach bootstrap.");
return BOOTSTRAP_NOT_PRIVILEGED;
}
if( !j->anonymous ) {
- job_log(j, LOG_NOTICE, "Non-anonymous job tried to move to Background session. Please set LimitLoadToSessionType in the launchd property list to \"Background\" instead.");
+ job_log(j, LOG_NOTICE, "Non-anonymous job tried to switch sessions. Please use LimitLoadToSessionType instead.");
return BOOTSTRAP_NOT_PRIVILEGED;
}
- job_log(j, LOG_NOTICE, "Detaching from console session.");
+ jobmgr_t target_jm = jobmgr_find_by_name(root_jobmgr, session_name);
+ if( target_jm == j->mgr ) {
+ job_log(j, LOG_WARNING, "Job tried to switch to its current session (%s).", session_name);
+ return BOOTSTRAP_NOT_PRIVILEGED;
+ }
+ target_jm = target_jm ? : jobmgr_new(j->mgr, requestor_port, MACH_PORT_NULL, false, session_name);
+ if( !job_assumes(j, target_jm != NULL) ) {
+ job_log(j, LOG_WARNING, "Could not find %s session!", session_name);
+ return BOOTSTRAP_NO_MEMORY;
+ }
+
/* Remove the job from it's current job manager. */
LIST_REMOVE(j, sle);
LIST_REMOVE(j, pid_hash_sle);
@@ -7531,25 +7560,25 @@
}
}
- /* Put the job into the background job manager. */
- LIST_INSERT_HEAD(&root_jobmgr->jobs, j, sle);
- LIST_INSERT_HEAD(&root_jobmgr->active_jobs[ACTIVE_JOB_HASH(j->p)], j, pid_hash_sle);
+ /* Put the job into the target job manager. */
+ LIST_INSERT_HEAD(&target_jm->jobs, j, sle);
+ LIST_INSERT_HEAD(&target_jm->active_jobs[ACTIVE_JOB_HASH(j->p)], j, pid_hash_sle);
if( ji ) {
- LIST_INSERT_HEAD(&root_jobmgr->global_env_jobs, j, global_env_sle);
+ LIST_INSERT_HEAD(&target_jm->global_env_jobs, j, global_env_sle);
}
- /* Move our Mach services over. */
+ /* Move our Mach services over if we're not in a flat namespace. */
if( !g_flat_mach_namespace && !SLIST_EMPTY(&j->machservices) ) {
struct machservice *msi = NULL, *msit = NULL;
SLIST_FOREACH_SAFE( msi, &j->machservices, sle, msit ) {
LIST_REMOVE(msi, name_hash_sle);
- LIST_INSERT_HEAD(&root_jobmgr->ms_hash[hash_ms(msi->name)], msi, name_hash_sle);
+ LIST_INSERT_HEAD(&target_jm->ms_hash[hash_ms(msi->name)], msi, name_hash_sle);
}
}
- j->mgr = root_jobmgr;
- *new_bsport = root_jobmgr->jm_port;
+ j->mgr = target_jm;
+ *new_bsport = target_jm->jm_port;
return KERN_SUCCESS;
}
@@ -7726,7 +7755,7 @@
*subsetportp = jmr->jm_port;
jmr->created_via_subset = true;
- job_log(j, LOG_NOTICE, "Job created a subset named \"%s\"", jmr->name);
+ job_log(j, LOG_DEBUG, "Job created a subset named \"%s\"", jmr->name);
return BOOTSTRAP_SUCCESS;
}
@@ -8103,3 +8132,57 @@
return max;
}
+
+/* See rdar://problem/6271234 */
+void
+eliminate_double_reboot(void)
+{
+ if( unlikely(!pid1_magic) ) {
+ return;
+ }
+
+ struct stat sb;
+ const char *argv[] = { "/etc/rc.deferredinstall", NULL };
+ char *try_again = "Will try again at next boot.";
+ int result = ~0;
+
+ if( unlikely(stat(argv[0], &sb) != -1) ) {
+ jobmgr_log(root_jobmgr, LOG_DEBUG | LOG_CONSOLE, "Going to run deferred install script.");
+
+ int wstatus;
+ pid_t p;
+
+ jobmgr_assumes(root_jobmgr, (errno = posix_spawnp(&p, argv[0], NULL, NULL, (char **)argv, environ)) == 0);
+
+ if (errno) {
+ jobmgr_log(root_jobmgr, LOG_WARNING | LOG_CONSOLE, "Couldn't run deferred install script! %s", try_again);
+ goto out;
+ }
+
+ if( !jobmgr_assumes(root_jobmgr, waitpid(p, &wstatus, 0) != -1) ) {
+ jobmgr_log(root_jobmgr, LOG_WARNING | LOG_CONSOLE, "Couldn't confirm that deferred install script exited successfully! %s", try_again);
+ goto out;
+ }
+
+ if( jobmgr_assumes(root_jobmgr, WIFEXITED(wstatus) != 0) ) {
+ if( jobmgr_assumes(root_jobmgr, (result = WEXITSTATUS(wstatus)) == EXIT_SUCCESS) ) {
+ jobmgr_log(root_jobmgr, LOG_DEBUG | LOG_CONSOLE, "Deferred install script completed successfully.");
+ } else {
+ jobmgr_log(root_jobmgr, LOG_WARNING | LOG_CONSOLE, "Deferred install script exited with status %d. %s", WEXITSTATUS(wstatus), try_again);
+ }
+ } else {
+ jobmgr_log(root_jobmgr, LOG_WARNING | LOG_CONSOLE, "Confirmed that deferred install script exited, but couldn't confirm that it was successful. %s", try_again);
+ }
+ }
+out:
+ if( result == 0 ) {
+ /* If the unlink(2) was to fail, it would be most likely fail with EBUSY. All the other
+ * failure cases for unlink(2) don't apply when we're running under PID 1 and have verified
+ * that the file exists. Outside of someone deliberately messing with us (like if /etc/rc.deferredinstall
+ * is actually a looping sym-link or a mount point for a filesystem) and I/O errors, we should be good.
+ */
+ if( !jobmgr_assumes(root_jobmgr, unlink(argv[0]) != -1) ) {
+ jobmgr_log(root_jobmgr, LOG_WARNING | LOG_CONSOLE, "Deferred install script couldn't be removed!");
+ }
+ }
+}
Modified: trunk/launchd/src/launchd_runtime.c
===================================================================
--- trunk/launchd/src/launchd_runtime.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/launchd_runtime.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -592,10 +592,7 @@
kevi = &kev[i];
if (kevi->filter) {
-/* Leave on for SnowLeopard development. We should really try and identify what bugs would
- * cause kevi->udata to be invalid.
- */
-#if 1
+#if 0
Dl_info dli;
/* Check if kevi->udata was either malloc(3)ed or is a valid function pointer.
@@ -606,7 +603,7 @@
runtime_ktrace(RTKT_LAUNCHD_BSD_KEVENT|DBG_FUNC_START, kevi->ident, kevi->filter, kevi->fflags);
(*((kq_callback *)kevi->udata))(kevi->udata, kevi);
runtime_ktrace0(RTKT_LAUNCHD_BSD_KEVENT|DBG_FUNC_END);
-#if 1
+#if 0
} else {
log_kevent_struct(LOG_EMERG, kevi, i);
}
@@ -1073,7 +1070,11 @@
tmp_options |= MACH_RCV_TIMEOUT;
if (!(tmp_options & MACH_SEND_TIMEOUT)) {
+ #if !TARGET_OS_EMBEDDED
to = busy_cnt ? runtime_idle_timeout : (_vproc_standby_timeout() * 1000);
+ #else
+ to = runtime_idle_timeout;
+ #endif
}
}
@@ -1510,7 +1511,9 @@
runtime_add_ref(void)
{
if (!pid1_magic) {
+ #if !TARGET_OS_EMBEDDED
_vproc_transaction_begin();
+ #endif
}
runtime_busy_cnt++;
}
@@ -1519,7 +1522,9 @@
runtime_del_ref(void)
{
if (!pid1_magic) {
+ #if !TARGET_OS_EMBEDDED
_vproc_transaction_end();
+ #endif
}
runtime_busy_cnt--;
}
@@ -1528,7 +1533,9 @@
runtime_add_weak_ref(void)
{
if (!pid1_magic) {
+ #if !TARGET_OS_EMBEDDED
_vproc_standby_begin();
+ #endif
}
runtime_standby_cnt++;
}
@@ -1537,7 +1544,9 @@
runtime_del_weak_ref(void)
{
if (!pid1_magic) {
+ #if !TARGET_OS_EMBEDDED
_vproc_standby_end();
+ #endif
}
runtime_standby_cnt--;
}
Modified: trunk/launchd/src/libbootstrap.c
===================================================================
--- trunk/launchd/src/libbootstrap.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/libbootstrap.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -21,6 +21,7 @@
#include "config.h"
#include "launch.h"
#include "launch_priv.h"
+#include "bootstrap.h"
#include "bootstrap_priv.h"
#include "vproc.h"
#include "vproc_priv.h"
Modified: trunk/launchd/src/liblaunch.c
===================================================================
--- trunk/launchd/src/liblaunch.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/liblaunch.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -208,16 +208,26 @@
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
+ /* The rules are as follows.
+ * - All users (including root) talk to their per-user launchd's by default.
+ * - If we have been invoked under sudo, talk to the system launchd.
+ * - If we're the root user and the __USE_SYSTEM_LAUNCHD environment variable is set, then
+ * talk to the system launchd.
+ */
if (where && where[0] != '\0') {
strncpy(sun.sun_path, where, sizeof(sun.sun_path));
- } else if ((!getenv("SUDO_COMMAND") || geteuid() != 0) && _vprocmgr_getsocket(spath) == 0) {
- size_t min_len;
-
- min_len = sizeof(sun.sun_path) < sizeof(spath) ? sizeof(sun.sun_path) : sizeof(spath);
-
- strncpy(sun.sun_path, spath, min_len);
} else {
- strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path));
+ if( (getenv("SUDO_COMMAND") || getenv("__USE_SYSTEM_LAUNCHD")) && geteuid() == 0 ) {
+ /* Talk to the system launchd. */
+ strncpy(sun.sun_path, LAUNCHD_SOCK_PREFIX "/sock", sizeof(sun.sun_path));
+ } else if( _vprocmgr_getsocket(spath) == 0 ) {
+ /* Talk to our per-user launchd. */
+ size_t min_len;
+
+ min_len = sizeof(sun.sun_path) < sizeof(spath) ? sizeof(sun.sun_path) : sizeof(spath);
+
+ strncpy(sun.sun_path, spath, min_len);
+ }
}
if ((lfd = _fd(socket(AF_UNIX, SOCK_STREAM, 0))) == -1) {
@@ -1265,26 +1275,5 @@
return -1;
}
-#define BEZEL_UI_HACK
-#ifdef BEZEL_UI_HACK
- #define BEZEL_UI_PATH "/System/Library/LoginPlugins/BezelServices.loginPlugin/Contents/Resources/BezelUI/BezelUIServer"
- #define BEZEL_UI_PLIST "/System/Library/LaunchAgents/com.apple.BezelUIServer.plist"
- #define BEZEL_UI_SERVICE "BezelUI"
-
- mach_port_t bezel_ui_server;
- struct stat sb;
- if (!(stat(BEZEL_UI_PLIST, &sb) == 0 && S_ISREG(sb.st_mode))) {
- if (bootstrap_create_server(bootstrap_port, BEZEL_UI_PATH, target_user, true, &bezel_ui_server) == BOOTSTRAP_SUCCESS) {
- mach_port_t srv;
-
- if (bootstrap_check_in(bezel_ui_server, BEZEL_UI_SERVICE, &srv) == BOOTSTRAP_SUCCESS) {
- mach_port_mod_refs(mach_task_self(), srv, MACH_PORT_RIGHT_RECEIVE, -1);
- }
-
- mach_port_deallocate(mach_task_self(), bezel_ui_server);
- }
- }
-#endif
-
return 1;
}
Modified: trunk/launchd/src/libvproc.c
===================================================================
--- trunk/launchd/src/libvproc.c 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/libvproc.c 2008-12-11 04:42:32 UTC (rev 23760)
@@ -69,18 +69,39 @@
kr = vproc_mig_setup_shmem(bootstrap_port, &shmem_port);
//assert(kr == 0);
- if (kr) return;
+ if (kr) {
+ /* rdar://problem/6416724
+ * If we fail to set up a shared memory page, just allocate a local chunk
+ * of memory. This way, processes can still introspect their own transaction
+ * counts if they're being run under a debugger. Moral of the story: Debug
+ * from the environment you intend to run in.
+ */
+ void *_vm_addr = malloc(sizeof(struct vproc_shmem_s));
+ if( !_vm_addr ) {
+ return;
+ }
+
+ _vproc_log(LOG_WARNING,
+ "Using private memory for transactions. You are likely running under a launchd agent or daemon under a debugger.\n"
+ "Please keep the following considerations in mind.\n"
+ "0. This process is not actually participating in Instant Off. It will only be able to keep track of its transaction count.\n"
+ "1. This process will not die after cleaning up its last transaction after it has received SIGTERM.\n"
+ "2. You are debugging your program in an environment that is very different from the one it will run under.\n"
+ "3. You can use the WaitForDebugger key to stall execution of your daemon or agent so that you can attach to it. See launchd.plist(5). "
+ "This only applies if you are debugging a launchd daemon or agent. If you are debugging a GUI application under Xcode, this consideration does not apply.\n");
+ vm_addr = (vm_address_t)_vm_addr;
+ } else {
+ kr = vm_map(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);
+
+ //assert(kr == 0);
+ if (kr) return;
+
+ kr = mach_port_deallocate(mach_task_self(), shmem_port);
+
+ //assert(kr == 0);
+ }
- kr = vm_map(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);
-
- //assert(kr == 0);
- if (kr) return;
-
- kr = mach_port_deallocate(mach_task_self(), shmem_port);
-
- //assert(kr == 0);
-
vproc_shmem = (struct vproc_shmem_s *)vm_addr;
}
@@ -101,8 +122,9 @@
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 */
-
+#if !TARGET_OS_EMBEDDED
_vproc_transaction_begin();
+#endif
return vpt;
}
@@ -110,6 +132,7 @@
void
_vproc_transaction_begin(void)
{
+#if !TARGET_OS_EMBEDDED
if (unlikely(vproc_shmem == NULL)) {
int po_r = pthread_once(&shmem_inited, vproc_client_init);
if (po_r != 0 || vproc_shmem == NULL) {
@@ -133,6 +156,7 @@
} while( !__sync_bool_compare_and_swap(&vproc_shmem->vp_shmem_transaction_cnt, old, old + 1) );
runtime_ktrace(RTKT_VPROC_TRANSACTION_INCREMENT, old + 1, 0, 0);
+#endif
}
size_t
@@ -174,6 +198,7 @@
}
void
+#if !TARGET_OS_EMBEDDED
_vproc_transaction_try_exit(int status)
{
if (unlikely(vproc_shmem == NULL)) {
@@ -185,6 +210,12 @@
_exit(status);
}
}
+#else
+_vproc_transaction_try_exit(int status __attribute__((unused)))
+{
+
+}
+#endif
void
vproc_transaction_end(vproc_t vp __attribute__((unused)), vproc_transaction_t vpt)
@@ -194,12 +225,15 @@
abort();
}
+#if !TARGET_OS_EMBEDDED
_vproc_transaction_end();
+#endif
}
void
_vproc_transaction_end(void)
{
+#if !TARGET_OS_EMBEDDED
typeof(vproc_shmem->vp_shmem_transaction_cnt) newval;
if (unlikely(vproc_shmem == NULL)) {
@@ -218,6 +252,7 @@
}
abort();
}
+#endif
}
vproc_standby_t
@@ -414,12 +449,14 @@
return !issetugid() ? _vproc_post_fork_ping() : NULL;
}
-vproc_err_t
-_vprocmgr_detach_from_console(uint32_t flags __attribute__((unused)))
+vproc_err_t
+_vprocmgr_switch_to_session(const char *target_session, vproc_flags_t flags __attribute__((unused)))
{
mach_port_t new_bsport = MACH_PORT_NULL;
- if( vproc_mig_detach_from_console(bootstrap_port, &new_bsport) != KERN_SUCCESS ) {
- return (vproc_err_t)_vprocmgr_detach_from_console;
+ kern_return_t kr = KERN_FAILURE;
+ if( (kr = vproc_mig_switch_to_session(bootstrap_port, mach_task_self(), (char *)target_session, &new_bsport)) != KERN_SUCCESS ) {
+ _vproc_log(LOG_NOTICE, "_vprocmgr_switch_to_session(): kr = 0x%x", kr);
+ return (vproc_err_t)_vprocmgr_switch_to_session;
}
task_set_bootstrap_port(mach_task_self(), new_bsport);
@@ -429,6 +466,12 @@
return !issetugid() ? _vproc_post_fork_ping() : NULL;
}
+vproc_err_t
+_vprocmgr_detach_from_console(vproc_flags_t flags __attribute__((unused)))
+{
+ return _vprocmgr_switch_to_session(VPROCMGR_SESSION_BACKGROUND, 0);
+}
+
pid_t
_spawn_via_launchd(const char *label, const char *const *argv, const struct spawn_via_launchd_attr *spawn_attrs, int struct_version)
{
Modified: trunk/launchd/src/protocol_vproc.defs
===================================================================
--- trunk/launchd/src/protocol_vproc.defs 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/protocol_vproc.defs 2008-12-11 04:42:32 UTC (rev 23760)
@@ -182,8 +182,10 @@
out __child_names : name_array_t, dealloc;
out __child_properties : bootstrap_property_array_t, dealloc);
-routine detach_from_console(
+routine switch_to_session(
__bs_port : job_t;
+ __req_port : mach_port_t;
+ __session_name : name_t;
out __new_bs_port : mach_port_make_send_t);
routine transaction_count_for_pid(
Modified: trunk/launchd/src/vproc_priv.h
===================================================================
--- trunk/launchd/src/vproc_priv.h 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd/src/vproc_priv.h 2008-12-11 04:42:32 UTC (rev 23760)
@@ -90,6 +90,7 @@
#define VPROCMGR_SESSION_SYSTEM "System"
vproc_err_t _vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type);
+vproc_err_t _vprocmgr_switch_to_session(const char *target_session, vproc_flags_t flags);
vproc_err_t _vprocmgr_detach_from_console(vproc_flags_t flags);
void _vproc_standby_begin(void) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_NA);
Modified: trunk/launchd.xcodeproj/project.pbxproj
===================================================================
--- trunk/launchd.xcodeproj/project.pbxproj 2008-11-26 06:56:06 UTC (rev 23759)
+++ trunk/launchd.xcodeproj/project.pbxproj 2008-12-11 04:42:32 UTC (rev 23760)
@@ -1079,6 +1079,7 @@
PREBINDING = NO;
PRODUCT_NAME = SystemStarter;
STRIP_STYLE = debugging;
+ VALID_ARCHS = "i386 ppc ppc64 ppc7400 ppc970 x86_64";
ZERO_LINK = NO;
};
name = Release;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/launchd-changes/attachments/20081210/bff1f74d/attachment-0001.html>
More information about the launchd-changes
mailing list