Revision: 22918 http://trac.macosforge.org/projects/launchd/changeset/22918 Author: zarzycki@apple.com Date: 2006-10-25 09:36:57 -0700 (Wed, 25 Oct 2006) Log Message: ----------- <rdar://problem/4637738> Need a launchd force on demand API Modified Paths: -------------- trunk/launchd/src/Makefile.am trunk/launchd/src/Makefile.in trunk/launchd/src/launchd_core_logic.c trunk/launchd/src/launchd_mig_types.defs trunk/launchd/src/liblaunch.c trunk/launchd/src/libvproc.c trunk/launchd/src/libvproc_internal.h trunk/launchd/src/libvproc_public.h trunk/launchd/src/protocol_job.defs Added Paths: ----------- trunk/launchd/src/libvproc_private.h Modified: trunk/launchd/src/Makefile.am =================================================================== --- trunk/launchd/src/Makefile.am 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/Makefile.am 2006-10-25 16:36:57 UTC (rev 22918) @@ -88,6 +88,7 @@ cp $(srcdir)/libbootstrap_public.h $(DESTDIR)/usr/include/servers/bootstrap_defs.h mkdir -p $(DESTDIR)/usr/local/include cp $(srcdir)/liblaunch_private.h $(DESTDIR)/usr/local/include/launch_priv.h + cp $(srcdir)/libvproc_private.h $(DESTDIR)/usr/local/include/vproc_priv.h mkdir -p $(DESTDIR)/$(sysconfdir)/mach_init.d mkdir -p $(DESTDIR)/$(sysconfdir)/mach_init_per_user.d mkdir -p $(DESTDIR)/Library/LaunchDaemons Modified: trunk/launchd/src/Makefile.in =================================================================== --- trunk/launchd/src/Makefile.in 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/Makefile.in 2006-10-25 16:36:57 UTC (rev 22918) @@ -1093,6 +1093,7 @@ @LIBS_ONLY_FALSE@ cp $(srcdir)/libbootstrap_public.h $(DESTDIR)/usr/include/servers/bootstrap_defs.h @LIBS_ONLY_FALSE@ mkdir -p $(DESTDIR)/usr/local/include @LIBS_ONLY_FALSE@ cp $(srcdir)/liblaunch_private.h $(DESTDIR)/usr/local/include/launch_priv.h +@LIBS_ONLY_FALSE@ cp $(srcdir)/libvproc_private.h $(DESTDIR)/usr/local/include/vproc_priv.h @LIBS_ONLY_FALSE@ mkdir -p $(DESTDIR)/$(sysconfdir)/mach_init.d @LIBS_ONLY_FALSE@ mkdir -p $(DESTDIR)/$(sysconfdir)/mach_init_per_user.d @LIBS_ONLY_FALSE@ mkdir -p $(DESTDIR)/Library/LaunchDaemons Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/launchd_core_logic.c 2006-10-25 16:36:57 UTC (rev 22918) @@ -1,6 +1,4 @@ /* - * Copyright (c) 2005 Apple Computer, Inc. All rights reserved. - * * @APPLE_APACHE_LICENSE_HEADER_START@ * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -237,7 +235,7 @@ anonymous:1; mode_t mask; unsigned int globargv:1, wait4debugger:1, transfer_bstrap:1, unload_at_exit:1, force_ppc:1, - stall_before_exec:1, only_once:1, currently_ignored:1; + stall_before_exec:1, only_once:1, currently_ignored:1, forced_peers_to_demand_mode:1; char label[0]; }; @@ -251,6 +249,8 @@ static void job_import_integer(job_t j, const char *key, long long value); static void job_import_dictionary(job_t j, const char *key, launch_data_t value); static void job_import_array(job_t j, const char *key, launch_data_t value); +static void job_dispatch_all(job_t j); +static bool job_set_global_on_demand(job_t j, bool val); static void job_watch(job_t j); static void job_ignore(job_t j); static void job_reap(job_t j); @@ -319,9 +319,10 @@ static int dir_has_files(job_t j, const char *path); static char **mach_cmd2argv(const char *string); -job_t root_job = NULL; -job_t gc_this_job = NULL; -size_t total_children = 0; +static size_t global_on_demand_cnt; +job_t root_job; +job_t gc_this_job; +size_t total_children; void simple_zombie_reaper(void *obj __attribute__((unused)), struct kevent *kev) @@ -655,6 +656,28 @@ } bool +job_set_global_on_demand(job_t j, bool val) +{ + if (j->forced_peers_to_demand_mode && val) { + return false; + } else if (!j->forced_peers_to_demand_mode && !val) { + return false; + } + + if ((j->forced_peers_to_demand_mode = val)) { + global_on_demand_cnt++; + } else { + global_on_demand_cnt--; + } + + if (global_on_demand_cnt == 0) { + job_dispatch_all(root_job); + } + + return true; +} + +bool job_setup_machport(job_t j) { mach_msg_size_t mxmsgsz; @@ -1547,6 +1570,18 @@ } void +job_dispatch_all(job_t j) +{ + job_t ji; + + SLIST_FOREACH(ji, &j->jobs, sle) { + job_dispatch_all(ji); + } + + job_dispatch(j, false); +} + +void job_dispatch(job_t j, bool kickstart) { /* @@ -1561,7 +1596,7 @@ return; } else if (job_useless(j)) { job_remove(j); - } else if (kickstart || job_keepalive(j)) { + } else if (global_on_demand_cnt == 0 && (kickstart || job_keepalive(j))) { job_start(j); } else { job_watch(j); @@ -2624,6 +2659,10 @@ { struct machservice *ms; + if (j->anonymous) { + return true; + } + if (j->req_port) { return true; } @@ -3535,6 +3574,40 @@ } kern_return_t +job_mig_get_integer(job_t j, get_set_int_key_t key, int64_t *val) +{ + kern_return_t kr = 0; + + switch (key) { + case LAST_EXIT_STATUS: + *val = j->last_exit_status; + break; + default: + kr = 1; + break; + } + + return kr; +} + +kern_return_t +job_mig_set_integer(job_t j, get_set_int_key_t key, int64_t val) +{ + kern_return_t kr = 0; + + switch (key) { + case GLOBAL_ON_DEMAND: + kr = job_set_global_on_demand(j, (bool)val) ? 0 : 1; + break; + default: + kr = 1; + break; + } + + return kr; +} + +kern_return_t job_mig_getsocket(job_t j, name_t spr) { if (!sockpath) { Modified: trunk/launchd/src/launchd_mig_types.defs =================================================================== --- trunk/launchd/src/launchd_mig_types.defs 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/launchd_mig_types.defs 2006-10-25 16:36:57 UTC (rev 22918) @@ -24,6 +24,7 @@ */ type pid_t = integer_t; +type get_set_int_key_t = integer_t; type cmd_t = c_string[512]; type cmd_array_t = ^array [] of cmd_t; type name_t = c_string[128]; Modified: trunk/launchd/src/liblaunch.c =================================================================== --- trunk/launchd/src/liblaunch.c 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/liblaunch.c 2006-10-25 16:36:57 UTC (rev 22918) @@ -19,8 +19,8 @@ */ #include "config.h" -#include "launch.h" -#include "launch_priv.h" +#include "liblaunch_public.h" +#include "liblaunch_private.h" #include <mach/mach.h> #include <libkern/OSByteOrder.h> @@ -1203,7 +1203,7 @@ if ((ldp = fexecv_as_user(login, u, g, ldargv)) == -1) return -1; - while (vprocmgr_getsocket(bootstrap_port, sp) != BOOTSTRAP_SUCCESS) + while (_vprocmgr_getsocket(bootstrap_port, sp) != BOOTSTRAP_SUCCESS) usleep(20000); setenv(LAUNCHD_SOCKET_ENV, sp, 1); Modified: trunk/launchd/src/libvproc.c =================================================================== --- trunk/launchd/src/libvproc.c 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/libvproc.c 2006-10-25 16:36:57 UTC (rev 22918) @@ -20,20 +20,20 @@ #include "config.h" #include "libvproc_public.h" +#include "libvproc_private.h" #include "libvproc_internal.h" #include <mach/mach.h> #include <mach/vm_map.h> #include <sys/param.h> #include <stdlib.h> +#include <errno.h> #include "liblaunch_public.h" #include "liblaunch_private.h" #include "protocol_vproc.h" -#include <errno.h> - kern_return_t _launchd_to_launchd(mach_port_t bp, mach_port_t *reqport, mach_port_t *rcvright, name_array_t *service_names, mach_msg_type_number_t *service_namesCnt, @@ -146,7 +146,32 @@ } kern_return_t -vprocmgr_getsocket(mach_port_t bp, name_t sockpath) +_vprocmgr_getsocket(mach_port_t bp, name_t sockpath) { return vproc_mig_getsocket(bp, sockpath); } + +vproc_err_t +_vproc_get_last_exit_status(int *wstatus) +{ + int64_t val; + + if (vproc_mig_get_integer(bootstrap_port, LAST_EXIT_STATUS, &val) == 0) { + *wstatus = (int)val; + return NULL; + } + + return (vproc_err_t)_vproc_get_last_exit_status; +} + +vproc_err_t +_vproc_set_global_on_demand(bool state) +{ + int64_t val = state ? ~0 : 0; + + if (vproc_mig_set_integer(bootstrap_port, GLOBAL_ON_DEMAND, val) == 0) { + return NULL; + } + + return (vproc_err_t)_vproc_set_global_on_demand; +} Modified: trunk/launchd/src/libvproc_internal.h =================================================================== --- trunk/launchd/src/libvproc_internal.h 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/libvproc_internal.h 2006-10-25 16:36:57 UTC (rev 22918) @@ -1,5 +1,5 @@ -#ifndef _VPROC_PRIVATE_H_ -#define _VPROC_PRIVATE_H_ +#ifndef _VPROC_INTERNAL_H_ +#define _VPROC_INTERNAL_H_ /* * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. * @@ -25,6 +25,10 @@ typedef char * _internal_string_t; typedef mach_port_t vproc_mig_t; +typedef enum { + LAST_EXIT_STATUS = 1, + GLOBAL_ON_DEMAND, +} get_set_int_key_t; #ifdef protocol_vproc_MSG_COUNT /* HACK */ @@ -44,7 +48,7 @@ name_array_t *service_names, mach_msg_type_number_t *service_namesCnt, mach_port_array_t *ports, mach_msg_type_number_t *portCnt); -kern_return_t vprocmgr_getsocket(mach_port_t bp, name_t); +kern_return_t _vprocmgr_getsocket(mach_port_t bp, name_t); kern_return_t Added: trunk/launchd/src/libvproc_private.h =================================================================== --- trunk/launchd/src/libvproc_private.h (rev 0) +++ trunk/launchd/src/libvproc_private.h 2006-10-25 16:36:57 UTC (rev 22918) @@ -0,0 +1,37 @@ +#ifndef _VPROC_PRIVATE_H_ +#define _VPROC_PRIVATE_H_ +/* + * Copyright (c) 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@ + */ + +#include <sys/cdefs.h> +#include <stdbool.h> + +__BEGIN_DECLS + +#pragma GCC visibility push(default) + +vproc_err_t _vproc_get_last_exit_status(int *wstatus); +vproc_err_t _vproc_set_global_on_demand(bool val); + +#pragma GCC visibility pop + +__END_DECLS + +#endif Modified: trunk/launchd/src/libvproc_public.h =================================================================== --- trunk/launchd/src/libvproc_public.h 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/libvproc_public.h 2006-10-25 16:36:57 UTC (rev 22918) @@ -24,11 +24,12 @@ __BEGIN_DECLS +typedef void * vproc_err_t; + #if 0 typedef void * vproc_t; typedef void * vprocmgr_t; -typedef void * vproc_err_t; /* By default, pass NULL for vprocmgr_t or vproc_t to get notions of self or "my manager" */ Modified: trunk/launchd/src/protocol_job.defs =================================================================== --- trunk/launchd/src/protocol_job.defs 2006-10-24 23:37:09 UTC (rev 22917) +++ trunk/launchd/src/protocol_job.defs 2006-10-25 16:36:57 UTC (rev 22918) @@ -109,3 +109,13 @@ routine uncork_fork( __bs_port : job_t); + +routine get_integer( + __bs_port : job_t; + __key : get_set_int_key_t; + out __val : int64_t); + +routine set_integer( + __bs_port : job_t; + __key : get_set_int_key_t; + __val : int64_t);