Projects
Browse Source     Search     Timeline     Wiki

Changeset 23574

Show
Ignore:
Timestamp:
2008-03-27 14:18:33 (7 months ago)
Author:
zarzycki@…
Message:

<rdar://problem/5752398> Need a darwin clean/dirty API

Location:
trunk/launchd/src
Files:
10 modified

Legend:

Unmodified
Added
Removed
  • trunk/launchd/src/Makefile.am

    r23536 r23574  
    11CWARN = -Wall -Wextra -Waggregate-return -Wfloat-equal -Wshadow -Wpacked -Wmissing-prototypes -Wmissing-declarations -Werror # gcc4.2: -Wstrict-overflow=4 # -Wpadded -Wconversion -Wstrict-aliasing=2 
    2 CTUNE = -fvisibility=hidden # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing 
     2CTUNE = -fvisibility=hidden -freorder-blocks # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing 
    33CMISC = -isysroot $(SDKROOT) -F$(SDKROOT)/System/Library/PrivateFrameworks -D__MigTypeCheck=1 -Dmig_external=__private_extern__ -D_DARWIN_USE_64_BIT_INODE=1 
    44AM_CFLAGS = $(CTUNE) $(CMISC) $(CWARN) 
     
    5858endif 
    5959 
    60 launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -freorder-blocks 
     60launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) 
    6161launchd_LDFLAGS = $(AM_LDFLAGS) -lbsm 
    6262launchd_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 
  • trunk/launchd/src/Makefile.in

    r23536 r23574  
    244244top_srcdir = @top_srcdir@ 
    245245CWARN = -Wall -Wextra -Waggregate-return -Wfloat-equal -Wshadow -Wpacked -Wmissing-prototypes -Wmissing-declarations -Werror # gcc4.2: -Wstrict-overflow=4 # -Wpadded -Wconversion -Wstrict-aliasing=2 
    246 CTUNE = -fvisibility=hidden # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing 
     246CTUNE = -fvisibility=hidden -freorder-blocks # gcc4.2: -fdiagnostics-show-option # -fstrict-aliasing 
    247247CMISC = -isysroot $(SDKROOT) -F$(SDKROOT)/System/Library/PrivateFrameworks -D__MigTypeCheck=1 -Dmig_external=__private_extern__ -D_DARWIN_USE_64_BIT_INODE=1 
    248248AM_CFLAGS = $(CTUNE) $(CMISC) $(CWARN) 
     
    263263@DO_EMBEDDED_MAGIC_FALSE@@LIBS_ONLY_FALSE@SystemStarter_LDFLAGS = $(AM_LDFLAGS) -framework CoreFoundation -framework IOKit 
    264264@DO_EMBEDDED_MAGIC_FALSE@@LIBS_ONLY_FALSE@SystemStarter_SOURCES = StartupItems.c IPC.c SystemStarter.c 
    265 @LIBS_ONLY_FALSE@launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) -freorder-blocks 
     265@LIBS_ONLY_FALSE@launchd_CFLAGS = -mdynamic-no-pic $(AM_CFLAGS) 
    266266@LIBS_ONLY_FALSE@launchd_LDFLAGS = $(AM_LDFLAGS) -lbsm 
    267267@LIBS_ONLY_FALSE@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 
  • trunk/launchd/src/launchd.plist.5

    r23532 r23574  
    124124.Xr glob 3 
    125125mechanism to update the program arguments before invocation. 
     126.It Sy EnableTransactions <boolean> 
     127This flag instructs 
     128.Nm launchd 
     129that the job promises to use 
     130.Xr vproc_transaction_begin 3 
     131and 
     132.Xr vproc_transaction_end 3 
     133to track outstanding transactions that need to be reconciled before the process can safely terminate. If no outstanding transactions are in progress, then 
     134.Nm launchd 
     135is free to send the SIGKILL signal. 
    126136.It Sy OnDemand <boolean> 
    127137This key was used in Mac OS X 10.4 to control whether a job was kept alive or not. The default was true. 
  • trunk/launchd/src/launchd_core_logic.c

    r23573 r23574  
    5151#include <sys/mount.h> 
    5252#include <sys/pipe.h> 
     53#include <sys/mman.h> 
    5354#include <net/if.h> 
    5455#include <netinet/in.h> 
     
    361362        char *stderrpath; 
    362363        char *alt_exc_handler; 
     364        struct vproc_shmem_s *shmem; 
    363365        struct machservice *lastlookup; 
    364366        unsigned int lastlookup_gennum; 
     
    385387        uint32_t min_run_time; 
    386388        uint32_t start_interval; 
    387         unsigned short checkedin:1, anonymous:1, debug:1, inetcompat:1, inetcompat_wait:1, 
     389        bool checkedin:1, anonymous:1, debug:1, inetcompat:1, inetcompat_wait:1, 
    388390                     ondemand:1, session_create:1, low_pri_io:1, no_init_groups:1, priv_port_has_senders:1, 
    389391                     importing_global_env:1, importing_hard_limits:1, setmask:1, legacy_mach_job:1, start_pending:1, 
     
    392394                     legacy_LS_job:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1, start_on_mount:1, 
    393395                     per_user:1, hopefully_exits_first:1, deny_unknown_mslookups:1, unload_at_mig_return:1, abandon_pg:1, 
    394                      poll_for_vfs_changes:1, deny_job_creation:1, __junk:11; 
     396                     poll_for_vfs_changes:1, deny_job_creation:1, kill_via_shmem:1, sent_kill_via_shmem:1; 
    395397        mode_t mask; 
    396398        const char label[0]; 
     
    562564job_stop(job_t j) 
    563565{ 
     566        int32_t newval = 1; 
     567 
    564568        if (unlikely(!j->p || j->anonymous)) { 
    565569                return; 
    566570        } 
    567571 
    568         job_assumes(j, runtime_kill(j->p, SIGTERM) != -1); 
     572        if (j->kill_via_shmem) { 
     573                if (j->shmem) { 
     574                        if (!j->sent_kill_via_shmem) { 
     575                                j->shmem->vp_shmem_flags |= VPROC_SHMEM_EXITING; 
     576                                newval = __sync_sub_and_fetch(&j->shmem->vp_shmem_transaction_cnt, 1); 
     577                                j->sent_kill_via_shmem = true; 
     578                        } else { 
     579                                newval = j->shmem->vp_shmem_transaction_cnt; 
     580                        } 
     581                } else { 
     582                        newval = -1; 
     583                } 
     584        } 
     585 
    569586        j->sent_sigterm_time = runtime_get_opaque_time(); 
    570587 
    571         if (j->exit_timeout) { 
    572                 job_assumes(j, kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER, 
    573                                         EV_ADD|EV_ONESHOT, NOTE_SECONDS, j->exit_timeout, j) != -1); 
    574         } 
    575  
    576         job_log(j, LOG_DEBUG, "Sent SIGTERM signal"); 
     588        if (newval < 0) { 
     589                job_kill(j); 
     590        } else { 
     591                job_assumes(j, runtime_kill(j->p, SIGTERM) != -1); 
     592 
     593                if (j->exit_timeout) { 
     594                        job_assumes(j, kevent_mod((uintptr_t)&j->exit_timeout, EVFILT_TIMER, 
     595                                                EV_ADD|EV_ONESHOT, NOTE_SECONDS, j->exit_timeout, j) != -1); 
     596                } 
     597 
     598                job_log(j, LOG_DEBUG, "Sent SIGTERM signal"); 
     599        } 
    577600} 
    578601 
     
    14531476                if (strcasecmp(key, LAUNCH_JOBKEY_ENABLEGLOBBING) == 0) { 
    14541477                        j->globargv = value; 
     1478                        found_key = true; 
     1479                } else if (strcasecmp(key, LAUNCH_JOBKEY_ENABLETRANSACTIONS) == 0) { 
     1480                        j->kill_via_shmem = value; 
    14551481                        found_key = true; 
    14561482                } else if (strcasecmp(key, LAUNCH_JOBKEY_ENTERKERNELDEBUGGERBEFOREKILL) == 0) { 
     
    22042230        job_log(j, LOG_DEBUG, "Reaping"); 
    22052231 
     2232        if (j->shmem) { 
     2233                job_assumes(j, munmap(j->shmem, getpagesize()) == 0); 
     2234        } 
     2235 
    22062236        if (unlikely(j->weird_bootstrap)) { 
    22072237                mach_msg_size_t mxmsgsz = sizeof(union __RequestUnion__job_mig_protocol_vproc_subsystem); 
     
    23362366        j->last_exit_status = status; 
    23372367        j->sent_sigkill = false; 
     2368        j->sent_kill_via_shmem = false; 
    23382369        j->p = 0; 
    23392370 
     
    54035434 
    54045435kern_return_t 
     5436job_mig_setup_shmem(job_t j, mach_port_t *shmem_port) 
     5437{ 
     5438        memory_object_size_t size_of_page, size_of_page_orig; 
     5439        kern_return_t kr; 
     5440 
     5441        if (!launchd_assumes(j != NULL)) { 
     5442                return BOOTSTRAP_NO_MEMORY; 
     5443        } 
     5444 
     5445        if (unlikely(j->anonymous)) { 
     5446                return BOOTSTRAP_NOT_PRIVILEGED; 
     5447        } 
     5448 
     5449        size_of_page_orig = size_of_page = getpagesize(); 
     5450 
     5451        if (!job_assumes(j, j->shmem = mmap(NULL, size_of_page, PROT_READ|PROT_WRITE, MAP_ANON, -1, 0))) { 
     5452                return BOOTSTRAP_NO_MEMORY; 
     5453        } 
     5454 
     5455        kr = mach_make_memory_entry_64(mach_task_self(), &size_of_page, 
     5456                        (memory_object_offset_t)((long)j->shmem), VM_PROT_DEFAULT, shmem_port, 0); 
     5457 
     5458        if (job_assumes(j, kr == 0)) { 
     5459                job_assumes(j, size_of_page == size_of_page_orig); 
     5460        } 
     5461 
     5462        return kr; 
     5463} 
     5464 
     5465kern_return_t 
    54055466job_mig_create_server(job_t j, cmd_t server_cmd, uid_t server_uid, boolean_t on_demand, mach_port_t *server_portp) 
    54065467{ 
  • trunk/launchd/src/liblaunch_public.h

    r23488 r23574  
    102102#define LAUNCH_JOBKEY_ABANDONPROCESSGROUP       "AbandonProcessGroup" 
    103103#define LAUNCH_JOBKEY_POLICIES                  "Policies" 
     104#define LAUNCH_JOBKEY_ENABLETRANSACTIONS        "EnableTransactions" 
    104105 
    105106#define LAUNCH_JOBPOLICY_DENYCREATINGOTHERJOBS  "DenyCreatingOtherJobs" 
  • trunk/launchd/src/libvproc.c

    r23563 r23574  
    3333#include <syslog.h> 
    3434#include <pthread.h> 
     35#include <signal.h> 
    3536#if HAVE_QUARANTINE 
    3637#include <quarantine.h> 
     
    4546#include "reboot2.h" 
    4647 
     48#define likely(x)       __builtin_expect((bool)(x), true) 
     49#define unlikely(x)     __builtin_expect((bool)(x), false) 
     50 
    4751static mach_port_t get_root_bootstrap_port(void); 
    4852 
     53const char *__crashreporter_info__; /* this should get merged with other versions of the symbol */ 
     54 
    4955static int64_t cached_pid = -1; 
     56static struct vproc_shmem_s *vproc_shmem; 
     57 
     58static void 
     59vproc_shmem_init(void) 
     60{ 
     61        vm_address_t vm_addr = 0; 
     62        mach_port_t shmem_port; 
     63        kern_return_t kr; 
     64 
     65        kr = vproc_mig_setup_shmem(bootstrap_port, &shmem_port); 
     66 
     67        if (unlikely(kr)) { 
     68                abort(); 
     69        } 
     70 
     71        kr = vm_map_64(mach_task_self(), &vm_addr, getpagesize(), 0, true, shmem_port, 0, false, 
     72                        VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE, VM_INHERIT_NONE); 
     73 
     74        if (unlikely(kr)) { 
     75                abort(); 
     76        } 
     77 
     78        vproc_shmem = (struct vproc_shmem_s *)vm_addr; 
     79} 
     80 
     81vproc_transaction_t 
     82vproc_transaction_begin(vproc_t vp __attribute__((unused))) 
     83{ 
     84        vproc_transaction_t vpt = (vproc_transaction_t)vproc_shmem_init; /* we need a "random" variable that is testable */ 
     85 
     86        _basic_vproc_transaction_begin(); 
     87 
     88        return vpt; 
     89} 
     90 
     91void 
     92_basic_vproc_transaction_begin(void) 
     93{ 
     94        int64_t newval; 
     95 
     96        if (unlikely(vproc_shmem == NULL)) { 
     97                vproc_shmem_init(); 
     98                if (vproc_shmem == NULL) { 
     99                        return; 
     100                } 
     101        } 
     102 
     103        newval = __sync_add_and_fetch(&vproc_shmem->vp_shmem_transaction_cnt, 1); 
     104 
     105        if (unlikely(newval < 1)) { 
     106                if (vproc_shmem->vp_shmem_flags & VPROC_SHMEM_EXITING) { 
     107                        raise(SIGKILL); 
     108                        __crashreporter_info__ = "raise(SIGKILL) failed"; 
     109                } else { 
     110                        __crashreporter_info__ = "Unbalanced: vproc_transaction_begin()"; 
     111                } 
     112                abort(); 
     113        } 
     114} 
     115 
     116void 
     117vproc_transaction_end(vproc_t vp __attribute__((unused)), vproc_transaction_t vpt) 
     118{ 
     119        if (unlikely(vpt != (vproc_transaction_t)vproc_shmem_init)) { 
     120                __crashreporter_info__ = "Bogus transaction handle passed to vproc_transaction_end() "; 
     121                abort(); 
     122        } 
     123 
     124        _basic_vproc_transaction_end(); 
     125} 
     126 
     127void 
     128_basic_vproc_transaction_end(void) 
     129{ 
     130        int32_t newval = __sync_sub_and_fetch(&vproc_shmem->vp_shmem_transaction_cnt, 1); 
     131 
     132        if (unlikely(newval < 0)) { 
     133                if (vproc_shmem->vp_shmem_flags & VPROC_SHMEM_EXITING) { 
     134                        raise(SIGKILL); 
     135                        __crashreporter_info__ = "raise(SIGKILL) failed"; 
     136                } else { 
     137                        __crashreporter_info__ = "Unbalanced: vproc_transaction_end()"; 
     138                } 
     139                abort(); 
     140        } 
     141} 
     142 
     143vproc_standby_t 
     144vproc_standby_begin(vproc_t vp __attribute__((unused))) 
     145{ 
     146        vproc_standby_t vpsb = (vproc_standby_t)vproc_shmem_init; /* we need a "random" variable that is testable */ 
     147        int64_t newval; 
     148 
     149        if (unlikely(vproc_shmem == NULL)) { 
     150                vproc_shmem_init(); 
     151                if (vproc_shmem == NULL) { 
     152                        return NULL; 
     153                } 
     154        } 
     155 
     156        newval = __sync_add_and_fetch(&vproc_shmem->vp_shmem_standby_cnt, 1); 
     157 
     158        if (unlikely(newval < 1)) { 
     159                __crashreporter_info__ = "Unbalanced: vproc_standby_begin()"; 
     160                abort(); 
     161        } 
     162 
     163        return vpsb; 
     164} 
     165 
     166void 
     167vproc_standby_end(vproc_t vp __attribute__((unused)), vproc_standby_t vpt) 
     168{ 
     169        int32_t newval; 
     170 
     171        if (unlikely(vpt != (vproc_standby_t)vproc_shmem_init)) { 
     172                __crashreporter_info__ = "Bogus standby handle passed to vproc_standby_end() "; 
     173                abort(); 
     174        } 
     175 
     176        newval = __sync_sub_and_fetch(&vproc_shmem->vp_shmem_standby_cnt, 1); 
     177 
     178        if (unlikely(newval < 0)) { 
     179                __crashreporter_info__ = "Unbalanced: vproc_standby_end()"; 
     180                abort(); 
     181        } 
     182} 
    50183 
    51184kern_return_t 
  • trunk/launchd/src/libvproc_internal.h

    r23563 r23574  
    3333typedef pid_t * pid_array_t; 
    3434typedef mach_port_t vproc_mig_t; 
     35 
     36#define VPROC_SHMEM_EXITING     0x1 
     37 
     38struct vproc_shmem_s { 
     39        int32_t vp_shmem_transaction_cnt; 
     40        int32_t vp_shmem_standby_cnt; 
     41        int32_t vp_shmem_flags; 
     42}; 
    3543 
    3644#ifdef protocol_vproc_MSG_COUNT 
  • trunk/launchd/src/libvproc_private.h

    r23533 r23574  
    7777vproc_err_t _vprocmgr_move_subset_to_user(uid_t target_user, const char *session_type); 
    7878 
     79void _basic_vproc_transaction_begin(void); 
     80void _basic_vproc_transaction_end(void); 
     81 
    7982#pragma GCC visibility pop 
    8083 
  • trunk/launchd/src/libvproc_public.h

    r23535 r23574  
    6868 * launchd jobs should update their property lists accordingly. 
    6969 * 
    70  * LaunchServices uses private methods to coordinate whether GUI applications 
    71  * have opted into this design. 
     70 * We plan to have LaunchServices use private methods to coordinate 
     71 * whether GUI applications have opted into this design. 
    7272 */ 
    7373 
     
    8181 
    8282/*! 
    83  * @function vproc_transaction_prepare 
     83 * @function vproc_transaction_begin 
     84 * 
     85 * @param       virtual_proc 
     86 * This is meant for future API improvements. Pass NULL for now. 
    8487 * 
    8588 * @result 
    86  * Returns an opaque handle to be passed to vproc_transaction_complete(). 
     89 * Returns an opaque handle to be passed to vproc_transaction_end(). 
    8790 * 
    8891 * @abstract 
     
    9093 */ 
    9194vproc_transaction_t 
    92 vproc_transaction_prepare(void); 
     95vproc_transaction_begin(vproc_t virtual_proc); 
    9396 
    9497/*! 
    95  * @function vproc_transaction_complete 
     98 * @function vproc_transaction_end 
     99 * 
     100 * @param       virtual_proc 
     101 * This is meant for future API improvements. Pass NULL for now. 
    96102 * 
    97103 * @param       handle 
    98  * The handle previously created with vproc_transaction_prepare(). 
     104 * The handle previously created with vproc_transaction_begin(). 
    99105 * 
    100106 * @abstract 
     
    105111 */ 
    106112void 
    107 vproc_transaction_complete(vproc_transaction_t handle); 
     113vproc_transaction_end(vproc_t virtual_proc, vproc_transaction_t handle); 
    108114 
    109115/*! 
     
    116122 
    117123/*! 
    118  * @function vproc_standby_prepare 
     124 * @function vproc_standby_begin 
     125 * 
     126 * @param       virtual_proc 
     127 * This is meant for future API improvements. Pass NULL for now. 
    119128 * 
    120129 * @result 
    121  * Returns an opaque handle to be passed to vproc_standby_complete(). 
     130 * Returns an opaque handle to be passed to vproc_standby_end(). 
    122131 * 
    123132 * @abstract 
     
    126135 */ 
    127136vproc_standby_t 
    128 vproc_standby_prepare(void); 
     137vproc_standby_begin(vproc_t virtual_proc); 
    129138 
    130139/*! 
    131  * @function vproc_standby_complete 
     140 * @function vproc_standby_end 
     141 * 
     142 * @param       virtual_proc 
     143 * This is meant for future API improvements. Pass NULL for now. 
    132144 * 
    133145 * @param       handle 
    134  * The handle previously created with vproc_standby_prepare(). 
     146 * The handle previously created with vproc_standby_begin(). 
    135147 * 
    136148 * @abstract 
     
    141153 */ 
    142154void 
    143 vproc_standby_complete(vproc_standby_t handle); 
     155vproc_standby_end(vproc_t virtual_proc, vproc_standby_t handle); 
    144156 
    145157#pragma GCC visibility pop 
  • trunk/launchd/src/protocol_job.defs

    r23539 r23574  
    9696        out     __subset_port   : mach_port_make_send_t); 
    9797 
    98 skip;   /* create_service prior to 10.6 */ 
     98routine setup_shmem( 
     99                __bs_port       : job_t; 
     100        out     __shmem_port    : mach_port_move_send_t); 
    99101 
    100102routine take_subset(