Changeset 23480
- Timestamp:
- 01/11/08 07:17:14 (11 months ago)
- Location:
- trunk/launchd/src
- Files:
-
- 5 modified
-
launchd.c (modified) (4 diffs)
-
launchd_core_logic.c (modified) (91 diffs)
-
launchd_runtime.h (modified) (1 diff)
-
launchd_unix_ipc.c (modified) (10 diffs)
-
launchd_unix_ipc.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/launchd/src/launchd.c
r23479 r23480 83 83 extern char **environ; 84 84 85 static void pfsystem_callback(void *, struct kevent *);85 INTERNAL_ABI static void pfsystem_callback(void *, struct kevent *); 86 86 87 87 static kq_callback kqpfsystem_callback = pfsystem_callback; … … 377 377 } 378 378 379 void379 INTERNAL_ABI void 380 380 pfsystem_callback(void *obj __attribute__((unused)), struct kevent *kev) 381 381 { … … 393 393 } 394 394 395 INTERNAL_ABI bool395 INTERNAL_ABI void 396 396 _log_launchd_bug(const char *rcs_rev, const char *path, unsigned int line, const char *test) 397 397 { … … 418 418 419 419 runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u: %s", file, line, buf, saved_errno, test); 420 421 return false; 422 } 420 } -
trunk/launchd/src/launchd_core_logic.c
r23479 r23480 264 264 LIST_HEAD(, job_s) active_jobs[ACTIVE_JOB_HASH_SIZE]; 265 265 LIST_HEAD(, machservice) ms_hash[MACHSERVICE_HASH_SIZE]; 266 LIST_HEAD(, job_s) global_env_jobs; 266 267 mach_port_t jm_port; 267 268 mach_port_t req_port; … … 276 277 277 278 #define jobmgr_assumes(jm, e) \ 278 ( likely(e) ? true : jobmgr_log_bug(jm, __LINE__))279 (unlikely(!(e)) ? jobmgr_log_bug(jm, __LINE__), false : true) 279 280 280 281 static jobmgr_t jobmgr_new(jobmgr_t jm, mach_port_t requestorport, mach_port_t transfer_port, bool sflag, const char *name); … … 290 291 static job_t job_mig_intran2(jobmgr_t jm, mach_port_t mport, pid_t upid); 291 292 static void job_export_all2(jobmgr_t jm, launch_data_t where); 292 static void jobmgr_callback(void *obj, struct kevent *kev);293 INTERNAL_ABI static void jobmgr_callback(void *obj, struct kevent *kev); 293 294 static void jobmgr_setup_env_from_other_jobs(jobmgr_t jm); 294 295 static void jobmgr_export_env_from_other_jobs(jobmgr_t jm, launch_data_t dict); … … 297 298 static void jobmgr_log(jobmgr_t jm, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); 298 299 /* static void jobmgr_log_error(jobmgr_t jm, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); */ 299 static booljobmgr_log_bug(jobmgr_t jm, unsigned int line);300 static void jobmgr_log_bug(jobmgr_t jm, unsigned int line); 300 301 301 302 #define DO_RUSAGE_SUMMATION 0 … … 308 309 LIST_ENTRY(job_s) pid_hash_sle; 309 310 LIST_ENTRY(job_s) label_hash_sle; 311 LIST_ENTRY(job_s) global_env_sle; 310 312 SLIST_HEAD(, socketgroup) sockets; 311 313 SLIST_HEAD(, calendarinterval) cal_intervals; … … 376 378 377 379 #define job_assumes(j, e) \ 378 ( likely(e) ? true : job_log_bug(j, __LINE__))380 (unlikely(!(e)) ? job_log_bug(j, __LINE__), false : true) 379 381 380 382 static void job_import_keys(launch_data_t obj, const char *key, void *context); … … 402 404 static void job_setup_exception_port(job_t j, task_t target_task); 403 405 static void job_reparent_hack(job_t j, const char *where); 404 static void job_callback(void *obj, struct kevent *kev);406 INTERNAL_ABI static void job_callback(void *obj, struct kevent *kev); 405 407 static void job_callback_proc(job_t j, int fflags); 406 408 static void job_callback_timer(job_t j, void *ident); … … 418 420 static void job_logv(job_t j, int pri, int err, const char *msg, va_list ap) __attribute__((format(printf, 4, 0))); 419 421 static void job_log_error(job_t j, int pri, const char *msg, ...) __attribute__((format(printf, 3, 4))); 420 static booljob_log_bug(job_t j, unsigned int line);422 static void job_log_bug(job_t j, unsigned int line); 421 423 static void job_log_stdouterr2(job_t j, const char *msg, ...); 422 424 static void job_set_exeception_port(job_t j, mach_port_t port); … … 681 683 } 682 684 683 static void685 INTERNAL_ABI static void 684 686 still_alive_with_check(void) 685 687 { … … 786 788 struct envitem *ei; 787 789 788 if (j->p && j->anonymous) { 789 job_reap(j); 790 } else if (j->p) { 791 job_log(j, LOG_DEBUG, "Removal pended until the job exits"); 792 793 if (!j->removal_pending) { 794 j->removal_pending = true; 795 job_stop(j); 796 } 797 798 return; 790 if (unlikely(j->p)) { 791 if (j->anonymous) { 792 job_reap(j); 793 } else { 794 job_log(j, LOG_DEBUG, "Removal pended until the job exits"); 795 796 if (!j->removal_pending) { 797 j->removal_pending = true; 798 job_stop(j); 799 } 800 return; 801 } 799 802 } 800 803 … … 867 870 free(j->prog); 868 871 } 869 if ( likely(j->argv)) {872 if (j->argv) { 870 873 free(j->argv); 871 874 } … … 1018 1021 1019 1022 /* jobs can easily be denied creation during shutdown */ 1020 if ( !jr) {1023 if (unlikely(jr == NULL)) { 1021 1024 goto out_bad; 1022 1025 } … … 1082 1085 } 1083 1086 1084 if ( len != sizeof(kp)) {1087 if (unlikely(len != sizeof(kp))) { 1085 1088 jobmgr_log(jm, LOG_DEBUG, "Tried to create an anonymous job for nonexistent PID: %u", anonpid); 1086 1089 errno = ESRCH; … … 1097 1100 } 1098 1101 1099 if ( kp.kp_proc.p_flag & P_SUGID) {1102 if (unlikely(kp.kp_proc.p_flag & P_SUGID)) { 1100 1103 jobmgr_log(jm, LOG_APPLEONLY, "Inconsistency: P_SUGID is set on PID %u: %s", anonpid, kp.kp_proc.p_comm); 1101 1104 } … … 1108 1111 kp_svgid = kp.kp_eproc.e_pcred.p_svgid; 1109 1112 1110 if ( kp_euid != kp_uid || kp_euid != kp_svuid || kp_uid != kp_svuid || kp_egid != kp_gid || kp_egid != kp_svgid || kp_gid != kp_svgid) {1113 if (unlikely(kp_euid != kp_uid || kp_euid != kp_svuid || kp_uid != kp_svuid || kp_egid != kp_gid || kp_egid != kp_svgid || kp_gid != kp_svgid)) { 1111 1114 jobmgr_log(jm, LOG_APPLEONLY, "Inconsistency: Mixed credentials (e/r/s UID %u/%u/%u GID %u/%u/%u) detected on PID %u: %s", 1112 1115 kp_euid, kp_uid, kp_svuid, kp_egid, kp_gid, kp_svgid, anonpid, kp.kp_proc.p_comm); … … 1129 1132 } 1130 1133 1131 if (jp && !jp->anonymous && !(kp.kp_proc.p_flag & P_EXEC)) {1134 if (jp && !jp->anonymous && unlikely(!(kp.kp_proc.p_flag & P_EXEC))) { 1132 1135 job_log(jp, LOG_APPLEONLY, "Performance and sanity: fork() without exec*(). Please switch to posix_spawn()"); 1133 1136 } … … 1135 1138 1136 1139 /* A total hack: Normally, job_new() returns an error during shutdown, but anonymous jobs are special. */ 1137 if ( (shutdown_state = jm->shutting_down)) {1140 if (unlikely(shutdown_state = jm->shutting_down)) { 1138 1141 jm->shutting_down = false; 1139 1142 } … … 1159 1162 } 1160 1163 1161 if ( shutdown_state && jm->hopefully_first_cnt == 0) {1164 if (unlikely(shutdown_state && jm->hopefully_first_cnt == 0)) { 1162 1165 job_log(jr, LOG_APPLEONLY, "This process showed up to the party while all the guests were leaving. Odds are that it will have a miserable time."); 1163 1166 } … … 1166 1169 } 1167 1170 1168 if ( shutdown_state) {1171 if (unlikely(shutdown_state)) { 1169 1172 jm->shutting_down = true; 1170 1173 } … … 1196 1199 } 1197 1200 1198 if ( label == AUTO_PICK_LEGACY_LABEL) {1201 if (unlikely(label == AUTO_PICK_LEGACY_LABEL)) { 1199 1202 bn = prog ? prog : basename((char *)argv[0]); /* prog for auto labels is kp.kp_kproc.p_comm */ 1200 1203 snprintf(auto_label, sizeof(auto_label), "%s.%s", sizeof(void *) == 8 ? "0xdeadbeeffeedface" : "0xbabecafe", bn); … … 1212 1215 } 1213 1216 1214 if ( label == auto_label) {1217 if (unlikely(label == auto_label)) { 1215 1218 snprintf((char *)j->label, strlen(label) + 1, "%p.%s", j, bn); 1216 1219 } else { … … 1430 1433 } 1431 1434 1432 if ( !found_key) {1435 if (unlikely(!found_key)) { 1433 1436 job_log(j, LOG_WARNING, "Unknown key for boolean: %s", key); 1434 1437 } … … 1532 1535 } 1533 1536 1534 if ( where2put) {1537 if (likely(where2put)) { 1535 1538 job_assumes(j, (*where2put = strdup(value)) != NULL); 1536 1539 } else { … … 1822 1825 job_t j; 1823 1826 1824 if (! launchd_assumes(pload != NULL)) {1827 if (!jobmgr_assumes(jm, pload != NULL)) { 1825 1828 errno = EINVAL; 1826 1829 return NULL; … … 1902 1905 1903 1906 LIST_FOREACH(ji, &label_hash[hash_label(label)], label_hash_sle) { 1904 if (ji->removal_pending) { 1905 continue; /* 5351245 */ 1906 } else if (ji->mgr->shutting_down) { 1907 continue; /* 5488633 */ 1907 if (unlikely(ji->removal_pending || ji->mgr->shutting_down)) { 1908 continue; /* 5351245 and 5488633 respectively */ 1908 1909 } 1909 1910 … … 1920 1921 jobmgr_find_by_pid(jobmgr_t jm, pid_t p, bool create_anon) 1921 1922 { 1922 job_t ji = NULL;1923 job_t ji; 1923 1924 1924 1925 LIST_FOREACH(ji, &jm->active_jobs[ACTIVE_JOB_HASH(p)], pid_hash_sle) { 1925 1926 if (ji->p == p) { 1926 break; 1927 } 1928 } 1929 1930 if (ji) { 1931 return ji; 1932 } else if (create_anon) { 1933 return job_new_anonymous(jm, p); 1934 } else { 1935 return NULL; 1936 } 1927 return ji; 1928 } 1929 } 1930 1931 return create_anon ? job_new_anonymous(jm, p) : NULL; 1937 1932 } 1938 1933 … … 2014 2009 */ 2015 2010 2016 if ( j && j != workaround_5477111 && j->unload_at_mig_return) {2011 if (unlikely(j && (j != workaround_5477111) && j->unload_at_mig_return)) { 2017 2012 job_log(j, LOG_NOTICE, "Unloading PID %u at MIG return.", j->p); 2018 2013 job_remove(j); … … 2467 2462 } else { 2468 2463 job_force_sampletool(j); 2469 if ( j->debug_before_kill) {2464 if (unlikely(j->debug_before_kill)) { 2470 2465 job_log(j, LOG_NOTICE, "Exit timeout elapsed. Entering the kernel debugger."); 2471 2466 job_assumes(j, host_reboot(mach_host_self(), HOST_REBOOT_DEBUGGER) == KERN_SUCCESS); … … 2507 2502 } 2508 2503 2509 void2504 INTERNAL_ABI void 2510 2505 jobmgr_callback(void *obj, struct kevent *kev) 2511 2506 { … … 2516 2511 case EVFILT_PROC: 2517 2512 jobmgr_reap_bulk(jm, kev); 2518 if (launchd_assumes(root_jobmgr != NULL)) { 2519 root_jobmgr = jobmgr_do_garbage_collection(root_jobmgr); 2520 } 2513 root_jobmgr = jobmgr_do_garbage_collection(root_jobmgr); 2521 2514 break; 2522 2515 case EVFILT_SIGNAL: … … 2567 2560 } 2568 2561 2569 void2562 INTERNAL_ABI void 2570 2563 job_callback(void *obj, struct kevent *kev) 2571 2564 { … … 2888 2881 } 2889 2882 2890 LIST_FOREACH(ji, &jm-> jobs,sle) {2883 LIST_FOREACH(ji, &jm->global_env_jobs, global_env_sle) { 2891 2884 SLIST_FOREACH(ei, &ji->global_env, sle) { 2892 2885 setenv(ei->key, ei->value, 1); … … 3240 3233 } 3241 3234 3242 bool 3235 void 3243 3236 jobmgr_log_bug(jobmgr_t jm, unsigned int line) 3244 3237 { … … 3264 3257 runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u", file, line, buf, saved_errno); 3265 3258 } 3266 3267 return false; 3268 } 3269 3270 bool 3259 } 3260 3261 void 3271 3262 job_log_bug(job_t j, unsigned int line) 3272 3263 { … … 3292 3283 runtime_syslog(LOG_NOTICE, "Bug: %s:%u (%s):%u", file, line, buf, saved_errno); 3293 3284 } 3294 3295 return false;3296 3285 } 3297 3286 … … 3785 3774 3786 3775 if (global) { 3776 if (SLIST_EMPTY(&j->global_env)) { 3777 LIST_INSERT_HEAD(&j->mgr->global_env_jobs, j, global_env_sle); 3778 } 3787 3779 SLIST_INSERT_HEAD(&j->global_env, ei, sle); 3788 3780 } else { … … 3800 3792 if (global) { 3801 3793 SLIST_REMOVE(&j->global_env, ei, envitem, sle); 3794 if (SLIST_EMPTY(&j->global_env)) { 3795 LIST_REMOVE(j, global_env_sle); 3796 } 3802 3797 } else { 3803 3798 SLIST_REMOVE(&j->env, ei, envitem, sle); … … 3951 3946 * launchctl.c for the other half of this hack. 3952 3947 */ 3953 if ( j->mgr->global_on_demand_cnt > 0 && strcmp(j->label, "com.apple.kextd") != 0) {3948 if (unlikely(j->mgr->global_on_demand_cnt > 0 && strcmp(j->label, "com.apple.kextd") != 0)) { 3954 3949 return false; 3955 3950 } 3956 3951 #else 3957 if ( j->mgr->global_on_demand_cnt > 0) {3952 if (unlikely(j->mgr->global_on_demand_cnt > 0)) { 3958 3953 return false; 3959 3954 } … … 3977 3972 } 3978 3973 if (status.mps_msgcount) { 3979 job_log(j, LOG_DEBUG, "KeepAlive check: job restarted due to%d queued Mach messages on service: %s",3974 job_log(j, LOG_DEBUG, "KeepAlive check: %d queued Mach messages on service: %s", 3980 3975 status.mps_msgcount, ms->name); 3981 3976 return true; … … 4140 4135 ms->per_pid = pid_local; 4141 4136 4142 if ( *serviceport == MACH_PORT_NULL) {4137 if (likely(*serviceport == MACH_PORT_NULL)) { 4143 4138 if (!job_assumes(j, launchd_mport_create_recv(&ms->port) == KERN_SUCCESS)) { 4144 4139 goto out_bad; … … 4188 4183 mach_port_t exc_port = the_exception_server; 4189 4184 4190 if ( j->alt_exc_handler) {4185 if (unlikely(j->alt_exc_handler)) { 4191 4186 ms = jobmgr_lookup_service(j->mgr, j->alt_exc_handler, true, 0); 4192 if ( ms) {4187 if (likely(ms)) { 4193 4188 exc_port = machservice_port(ms); 4194 4189 } else { 4195 4190 job_log(j, LOG_WARNING, "Falling back to default Mach exception handler. Could not find: %s", j->alt_exc_handler); 4196 4191 } 4197 } else if ( j->internal_exc_handler) {4192 } else if (unlikely(j->internal_exc_handler)) { 4198 4193 exc_port = runtime_get_kernel_port(); 4199 } else if ( !exc_port) {4194 } else if (unlikely(!exc_port)) { 4200 4195 return; 4201 4196 } … … 4207 4202 #endif 4208 4203 4209 if ( target_task) {4204 if (likely(target_task)) { 4210 4205 job_assumes(j, task_set_exception_ports(target_task, EXC_MASK_CRASH, exc_port, 4211 4206 EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, f) == KERN_SUCCESS); … … 4222 4217 job_set_exeception_port(job_t j, mach_port_t port) 4223 4218 { 4224 if ( !the_exception_server) {4219 if (unlikely(!the_exception_server)) { 4225 4220 the_exception_server = port; 4226 4221 job_setup_exception_port(j, 0); … … 4299 4294 mach_port_t p = MACH_PORT_NULL; 4300 4295 4301 if ( (ms = jobmgr_lookup_service(j->mgr, key, false, 0))) {4296 if (unlikely(ms = jobmgr_lookup_service(j->mgr, key, false, 0))) { 4302 4297 job_log(j, LOG_WARNING, "Conflict with job: %s over Mach service: %s", ms->job->label, key); 4303 4298 return; 4304 4299 } 4305 4300 4306 if ((ms = machservice_new(j, key, &p, false)) == NULL) { 4307 job_log_error(j, LOG_WARNING, "Cannot add service: %s", key); 4301 if (!job_assumes(j, (ms = machservice_new(j, key, &p, false)) != NULL)) { 4308 4302 return; 4309 4303 } … … 4326 4320 } 4327 4321 4328 if ( !jm->shutting_down) {4322 if (likely(!jm->shutting_down)) { 4329 4323 return jm; 4330 4324 } … … 4394 4388 struct kinfo_proc *kp; 4395 4389 4396 if ( jm->parentmgr || getpid() != 1) {4390 if (likely(jm->parentmgr || getpid() != 1)) { 4397 4391 return; 4398 4392 } … … 4414 4408 const char *n = kp[i].kp_proc.p_comm; 4415 4409 4416 if ( p_i == 0 || p_i == 1) {4410 if (unlikely(p_i == 0 || p_i == 1)) { 4417 4411 kp_skipped++; 4418 4412 continue; … … 4463 4457 launchd_assert(offsetof(struct jobmgr_s, kqjobmgr_callback) == 0); 4464 4458 4465 if ( jm && requestorport == MACH_PORT_NULL) {4459 if (unlikely(jm && requestorport == MACH_PORT_NULL)) { 4466 4460 jobmgr_log(jm, LOG_ERR, "Mach sub-bootstrap create request requires a requester port"); 4467 4461 return NULL; … … 4610 4604 if (jm == root_jobmgr) { 4611 4605 if (port == inherited_bootstrap_port) { 4612 launchd_assumes(launchd_mport_deallocate(port) == KERN_SUCCESS);4606 jobmgr_assumes(jm, launchd_mport_deallocate(port) == KERN_SUCCESS); 4613 4607 inherited_bootstrap_port = MACH_PORT_NULL; 4614 4608 … … 4639 4633 { 4640 4634 struct machservice *ms; 4635 job_t target_j; 4641 4636 4642 4637 if (target_pid) { 4643 jobmgr_assumes(jm, !check_parent); 4644 } 4645 4646 LIST_FOREACH(ms, &jm->ms_hash[hash_ms(name)], name_hash_sle) { 4647 if ((target_pid && ms->per_pid && ms->job->p == target_pid) || (!target_pid && !ms->per_pid)) { 4648 if (strcmp(name, ms->name) == 0) { 4638 //jobmgr_assumes(jm, !check_parent); 4639 4640 if (unlikely((target_j = jobmgr_find_by_pid(jm, target_pid, false)) == NULL)) { 4641 return NULL; 4642 } 4643 4644 SLIST_FOREACH(ms, &target_j->machservices, sle) { 4645 if (ms->per_pid && strcmp(name, ms->name) == 0) { 4649 4646 return ms; 4650 4647 } 4651 4648 } 4652 } 4653 4654 if (jm->parentmgr == NULL) { 4649 4655 4650 return NULL; 4656 4651 } 4657 4652 4658 if (!check_parent) { 4653 LIST_FOREACH(ms, &jm->ms_hash[hash_ms(name)], name_hash_sle) { 4654 if (!ms->per_pid && strcmp(name, ms->name) == 0) { 4655 return ms; 4656 } 4657 } 4658 4659 if (jm->parentmgr == NULL || !check_parent) { 4659 4660 return NULL; 4660 4661 } … … 4696 4697 machservice_delete(job_t j, struct machservice *ms, bool port_died) 4697 4698 { 4698 if ( ms->debug_on_close) {4699 if (unlikely(ms->debug_on_close)) { 4699 4700 job_log(j, LOG_NOTICE, "About to enter kernel debugger because of Mach port: 0x%x", ms->port); 4700 4701 job_assumes(j, host_reboot(mach_host_self(), HOST_REBOOT_DEBUGGER) == KERN_SUCCESS); … … 4707 4708 job_assumes(j, launchd_mport_deallocate(ms->port) == KERN_SUCCESS); 4708 4709 4709 if ( ms->port == the_exception_server) {4710 if (unlikely(ms->port == the_exception_server)) { 4710 4711 the_exception_server = 0; 4711 4712 } … … 5277 5278 #ifdef LET_MERE_MORTALS_ADD_SERVERS_TO_PID1 5278 5279 if (getpid() == 1) { 5279 if ( ldc.euid && server_uid && (ldc.euid != server_uid)) {5280 if (unlikely(ldc.euid && server_uid && (ldc.euid != server_uid))) { 5280 5281 job_log(j, LOG_WARNING, "Server create: \"%s\": Will run as UID %d, not UID %d as they told us to", 5281 5282 server_cmd, ldc.euid, server_uid); … … 5285 5286 #endif 5286 5287 if (getuid()) { 5287 if ( server_uid != getuid()) {5288 if (unlikely(server_uid != getuid())) { 5288 5289 job_log(j, LOG_WARNING, "Server create: \"%s\": As UID %d, we will not be able to switch to UID %d", 5289 5290 server_cmd, getuid(), server_uid); … … 5294 5295

