<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[23446] trunk/launchd/src</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd><a href="http://trac.macosforge.org/projects/launchd/changeset/23446">23446</a></dd>
<dt>Author</dt> <dd>zarzycki@apple.com</dd>
<dt>Date</dt> <dd>2007-10-23 13:37:23 -0700 (Tue, 23 Oct 2007)</dd>
</dl>

<h3>Log Message</h3>
<pre>Aggressive logging.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunklaunchdsrclaunchctlc">trunk/launchd/src/launchctl.c</a></li>
<li><a href="#trunklaunchdsrclaunchd_core_logicc">trunk/launchd/src/launchd_core_logic.c</a></li>
<li><a href="#trunklaunchdsrclaunchd_runtimec">trunk/launchd/src/launchd_runtime.c</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunklaunchdsrclaunchctlc"></a>
<div class="modfile"><h4>Modified: trunk/launchd/src/launchctl.c (23445 => 23446)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/launchd/src/launchctl.c        2007-10-23 15:47:01 UTC (rev 23445)
+++ trunk/launchd/src/launchctl.c        2007-10-23 20:37:23 UTC (rev 23446)
</span><span class="lines">@@ -74,8 +74,11 @@
</span><span class="cx"> #include &lt;bootfiles.h&gt;
</span><span class="cx"> #include &lt;sysexits.h&gt;
</span><span class="cx"> #include &lt;util.h&gt;
</span><ins>+#include &lt;spawn.h&gt;
</ins><span class="cx"> 
</span><ins>+extern char **environ;
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx"> #define LAUNCH_SECDIR &quot;/tmp/launch-XXXXXX&quot;
</span><span class="cx"> 
</span><span class="cx"> #define MACHINIT_JOBKEY_ONDEMAND        &quot;OnDemand&quot;
</span><span class="lines">@@ -132,7 +135,7 @@
</span><span class="cx"> static void _log_launchctl_bug(const char *rcs_rev, const char *path, unsigned int line, const char *test);
</span><span class="cx"> static void loopback_setup_ipv4(void);
</span><span class="cx"> static void loopback_setup_ipv6(void);
</span><del>-static pid_t fwexec(const char *const *argv, bool _wait);
</del><ins>+static pid_t fwexec(const char *const *argv, int *wstatus);
</ins><span class="cx"> static void do_potential_fsck(void);
</span><span class="cx"> static bool path_check(const char *path);
</span><span class="cx"> static bool is_safeboot(void);
</span><span class="lines">@@ -1404,19 +1407,19 @@
</span><span class="cx"> 
</span><span class="cx">         if (path_check(&quot;/etc/rc.server&quot;)) {
</span><span class="cx">                 const char *rcserver_tool[] = { _PATH_BSHELL, &quot;/etc/rc.server&quot;, NULL };
</span><del>-                assumes(fwexec(rcserver_tool, true) != -1);
</del><ins>+                assumes(fwexec(rcserver_tool, NULL) != -1);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         apply_sysctls_from_file(&quot;/etc/sysctl.conf&quot;);
</span><span class="cx"> 
</span><span class="cx">         if (path_check(&quot;/etc/rc.cdrom&quot;)) {
</span><span class="cx">                 const char *rccdrom_tool[] = { _PATH_BSHELL, &quot;/etc/rc.cdrom&quot;, &quot;multiuser&quot;, NULL };
</span><del>-                assumes(fwexec(rccdrom_tool, true) != -1);
</del><ins>+                assumes(fwexec(rccdrom_tool, NULL) != -1);
</ins><span class="cx">                 assumes(reboot(RB_HALT) != -1);
</span><span class="cx">                 _exit(EXIT_FAILURE);
</span><span class="cx">         } else if (is_netboot()) {
</span><span class="cx">                 const char *rcnetboot_tool[] = { _PATH_BSHELL, &quot;/etc/rc.netboot&quot;, &quot;init&quot;, NULL };
</span><del>-                if (!assumes(fwexec(rcnetboot_tool, true) != -1)) {
</del><ins>+                if (!assumes(fwexec(rcnetboot_tool, NULL) != -1)) {
</ins><span class="cx">                         assumes(reboot(RB_HALT) != -1);
</span><span class="cx">                         _exit(EXIT_FAILURE);
</span><span class="cx">                 }
</span><span class="lines">@@ -1432,12 +1435,12 @@
</span><span class="cx"> 
</span><span class="cx">         if (path_check(&quot;/etc/fstab&quot;)) {
</span><span class="cx">                 const char *mount_tool[] = { &quot;mount&quot;, &quot;-vat&quot;, &quot;nonfs&quot;, NULL };
</span><del>-                assumes(fwexec(mount_tool, true) != -1);
</del><ins>+                assumes(fwexec(mount_tool, NULL) != -1);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (path_check(&quot;/etc/rc.installer_cleanup&quot;)) {
</span><span class="cx">                 const char *rccleanup_tool[] = { _PATH_BSHELL, &quot;/etc/rc.installer_cleanup&quot;, &quot;multiuser&quot;, NULL };
</span><del>-                assumes(fwexec(rccleanup_tool, true) != -1);
</del><ins>+                assumes(fwexec(rccleanup_tool, NULL) != -1);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         empty_dir(_PATH_VARRUN, NULL);
</span><span class="lines">@@ -1446,7 +1449,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (path_check(&quot;/usr/libexec/dirhelper&quot;)) {
</span><span class="cx">                 const char *dirhelper_tool[] = { &quot;/usr/libexec/dirhelper&quot;, &quot;-machineBoot&quot;, NULL };
</span><del>-                assumes(fwexec(dirhelper_tool, true) != -1);
</del><ins>+                assumes(fwexec(dirhelper_tool, NULL) != -1);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         assumes(touch_file(_PATH_UTMPX, DEFFILEMODE) != -1);
</span><span class="lines">@@ -1454,7 +1457,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (path_check(&quot;/etc/security/rc.audit&quot;)) {
</span><span class="cx">                 const char *audit_tool[] = { _PATH_BSHELL, &quot;/etc/security/rc.audit&quot;, NULL };
</span><del>-                assumes(fwexec(audit_tool, true) != -1);
</del><ins>+                assumes(fwexec(audit_tool, NULL) != -1);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         do_BootCache_magic(BOOTCACHE_START);
</span><span class="lines">@@ -1553,7 +1556,7 @@
</span><span class="cx">                 return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        fwexec(bcc_tool, true);
</del><ins>+        fwexec(bcc_tool, NULL);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> int
</span><span class="lines">@@ -2556,7 +2559,7 @@
</span><span class="cx">         setgid(getgid());
</span><span class="cx">         setuid(getuid());
</span><span class="cx"> 
</span><del>-        if (fwexec((const char *const *)argv + 2, true) == -1) {
</del><ins>+        if (fwexec((const char *const *)argv + 2, NULL) == -1) {
</ins><span class="cx">                 fprintf(stderr, &quot;%s bsexec failed: %s\n&quot;, getprogname(), strerror(errno));
</span><span class="cx">                 return 1;
</span><span class="cx">         }
</span><span class="lines">@@ -2703,31 +2706,27 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> pid_t
</span><del>-fwexec(const char *const *argv, bool _wait)
</del><ins>+fwexec(const char *const *argv, int *wstatus)
</ins><span class="cx"> {
</span><del>-        int wstatus;
</del><ins>+        int wstatus2;
</ins><span class="cx">         pid_t p;
</span><span class="cx"> 
</span><del>-        switch ((p = fork())) {
-        case -1:
-                break;
-        case 0:
-                if (!_wait) {
-                        setsid();
-                }
-                execvp(argv[0], (char *const *)argv);
-                _exit(EXIT_FAILURE);
-                break;
-        default:
-                if (!_wait)
-                        return p;
-                if (p == waitpid(p, &amp;wstatus, 0)) {
-                        if (WIFEXITED(wstatus) &amp;&amp; WEXITSTATUS(wstatus) == EXIT_SUCCESS)
-                                return p;
-                }
-                break;
</del><ins>+        errno = posix_spawnp(&amp;p, argv[0], NULL, NULL, (char **)argv, environ);
+
+        if (errno) {
+                return -1;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (waitpid(p, wstatus ? wstatus : &amp;wstatus2, 0) == -1) {
+                return -1;
+        }
+
+        if (wstatus) {
+                return p;
+        } else if (WIFEXITED(wstatus2) &amp;&amp; WEXITSTATUS(wstatus2) == EXIT_SUCCESS) {
+                return p;
+        }
+
</ins><span class="cx">         return -1;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2755,12 +2754,12 @@
</span><span class="cx">                 }
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><del>-                if (fwexec(fsck_tool, true) != -1) {
</del><ins>+                if (fwexec(fsck_tool, NULL) != -1) {
</ins><span class="cx">                         goto out;
</span><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (fwexec(safe_fsck_tool, true) != -1) {
</del><ins>+        if (fwexec(safe_fsck_tool, NULL) != -1) {
</ins><span class="cx">                 goto out;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -2778,7 +2777,7 @@
</span><span class="cx">          * assumes(mount(sfs.f_fstypename, &quot;/&quot;, MNT_UPDATE, NULL) != -1);
</span><span class="cx">          */
</span><span class="cx"> 
</span><del>-        assumes(fwexec(remount_tool, true) != -1);
</del><ins>+        assumes(fwexec(remount_tool, NULL) != -1);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool
</span><span class="lines">@@ -2930,7 +2929,7 @@
</span><span class="cx">                         goto skip_sysctl_tool;
</span><span class="cx">                 }
</span><span class="cx">                 sysctl_tool[2] = val;
</span><del>-                assumes(fwexec(sysctl_tool, true) != -1);
</del><ins>+                assumes(fwexec(sysctl_tool, NULL) != -1);
</ins><span class="cx"> skip_sysctl_tool:
</span><span class="cx">                 free(tmpstr);
</span><span class="cx">         }
</span><span class="lines">@@ -3097,14 +3096,10 @@
</span><span class="cx"> 
</span><span class="cx">         CFRelease(bootrootProp);
</span><span class="cx"> 
</span><del>-        if (!assumes((p = fwexec(kextcache_tool, false)) != -1)) {
</del><ins>+        if (!assumes((p = fwexec(kextcache_tool, &amp;wstatus)) != -1)) {
</ins><span class="cx">                 return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!assumes(waitpid(p, &amp;wstatus, 0) != -1)) {
-                return;
-        }
-
</del><span class="cx">         if (WIFEXITED(wstatus) &amp;&amp; WEXITSTATUS(wstatus) == EX_OSFILE) {
</span><span class="cx">                 assumes(reboot(RB_AUTOBOOT) != -1);
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunklaunchdsrclaunchd_core_logicc"></a>
<div class="modfile"><h4>Modified: trunk/launchd/src/launchd_core_logic.c (23445 => 23446)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/launchd/src/launchd_core_logic.c        2007-10-23 15:47:01 UTC (rev 23445)
+++ trunk/launchd/src/launchd_core_logic.c        2007-10-23 20:37:23 UTC (rev 23446)
</span><span class="lines">@@ -132,7 +132,6 @@
</span><span class="cx">         LIST_ENTRY(machservice) name_hash_sle;
</span><span class="cx">         LIST_ENTRY(machservice) port_hash_sle;
</span><span class="cx">         job_t                        job;
</span><del>-        uint64_t                bad_perf_cnt;
</del><span class="cx">         unsigned int                gen_num;
</span><span class="cx">         mach_port_name_t        port;
</span><span class="cx">         unsigned int                isActive:1, reset:1, recv:1, hide:1, kUNCServer:1, per_user_hack:1, debug_on_close:1, per_pid:1, special_port_num:10;
</span><span class="lines">@@ -358,11 +357,11 @@
</span><span class="cx">                      ondemand:1, session_create:1, low_pri_io:1, no_init_groups:1, priv_port_has_senders:1,
</span><span class="cx">                      importing_global_env:1, importing_hard_limits:1, setmask:1, legacy_mach_job:1, start_pending:1;
</span><span class="cx">         mode_t mask;
</span><del>-        unsigned int globargv:1, wait4debugger:1, unload_at_exit:1, stall_before_exec:1, only_once:1,
</del><ins>+        unsigned int globargv:1, wait4debugger:1, internal_exc_handler:1, stall_before_exec:1, only_once:1,
</ins><span class="cx">                      currently_ignored:1, forced_peers_to_demand_mode:1, setnice:1, hopefully_exits_last:1, removal_pending:1,
</span><del>-                     wait4pipe_eof:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1, start_on_mount:1,
</del><ins>+                     legacy_LS_job:1, sent_sigkill:1, debug_before_kill:1, weird_bootstrap:1, start_on_mount:1,
</ins><span class="cx">                      per_user:1, hopefully_exits_first:1, deny_unknown_mslookups:1, unload_at_mig_return:1, abandon_pg:1,
</span><del>-                     poll_for_vfs_changes:1, internal_exc_handler:1;
</del><ins>+                     poll_for_vfs_changes:1;
</ins><span class="cx">         const char label[0];
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -396,7 +395,7 @@
</span><span class="cx"> static bool job_setup_machport(job_t j);
</span><span class="cx"> static void job_setup_fd(job_t j, int target_fd, const char *path, int flags);
</span><span class="cx"> static void job_postfork_become_user(job_t j);
</span><del>-static void job_find_and_blame_pids_with_weird_uids(job_t j);
</del><ins>+static void job_log_pids_with_weird_uids(job_t j);
</ins><span class="cx"> static void job_force_sampletool(job_t j);
</span><span class="cx"> static void job_setup_exception_port(job_t j, task_t target_task);
</span><span class="cx"> static void job_reparent_hack(job_t j, const char *where);
</span><span class="lines">@@ -405,6 +404,7 @@
</span><span class="cx"> static void job_callback_timer(job_t j, void *ident);
</span><span class="cx"> static void job_callback_read(job_t j, int ident);
</span><span class="cx"> static void job_log_stray_pg(job_t j);
</span><ins>+static void job_log_chidren_without_exec(job_t j);
</ins><span class="cx"> static job_t job_new_anonymous(jobmgr_t jm, pid_t anonpid);
</span><span class="cx"> static job_t job_new(jobmgr_t jm, const char *label, const char *prog, const char *const *argv);
</span><span class="cx"> static job_t job_new_via_mach_init(job_t j, const char *cmd, uid_t uid, bool ond);
</span><span class="lines">@@ -1034,9 +1034,10 @@
</span><span class="cx">         int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, anonpid };
</span><span class="cx">         struct kinfo_proc kp;
</span><span class="cx">         size_t len = sizeof(kp);
</span><del>-        const char *zombie = NULL;
</del><span class="cx">         bool shutdown_state;
</span><span class="cx">         job_t jp = NULL, jr = NULL;
</span><ins>+        uid_t kp_euid, kp_uid, kp_svuid;
+        gid_t kp_egid, kp_gid, kp_svgid;
</ins><span class="cx"> 
</span><span class="cx">         if (!jobmgr_assumes(jm, anonpid != 0)) {
</span><span class="cx">                 return NULL;
</span><span class="lines">@@ -1061,10 +1062,25 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (kp.kp_proc.p_stat == SZOMB) {
</span><del>-                jobmgr_log(jm, LOG_DEBUG, &quot;Tried to create an anonymous job for zombie PID: %u&quot;, anonpid);
-                zombie = &quot;zombie&quot;;
</del><ins>+                jobmgr_log(jm, LOG_DEBUG, &quot;Tried to create an anonymous job for zombie PID %u: %s&quot;, anonpid, kp.kp_proc.p_comm);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (kp.kp_proc.p_flag &amp; P_SUGID) {
+                jobmgr_log(jm, LOG_APPLEONLY, &quot;Inconsistency: P_SUGID is set on PID %u: %s&quot;, anonpid, kp.kp_proc.p_comm);
+        }
+
+        kp_euid = kp.kp_eproc.e_ucred.cr_uid;
+        kp_uid = kp.kp_eproc.e_pcred.p_ruid;
+        kp_svuid = kp.kp_eproc.e_pcred.p_svuid;
+        kp_egid = kp.kp_eproc.e_ucred.cr_gid;
+        kp_gid = kp.kp_eproc.e_pcred.p_rgid;
+        kp_svgid = kp.kp_eproc.e_pcred.p_svgid;
+
+        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) {
+                jobmgr_log(jm, LOG_APPLEONLY, &quot;Inconsistency: Mixed credentials (e/r/s UID %u/%u/%u GID %u/%u/%u) detected on PID %u: %s&quot;,
+                                kp_euid, kp_uid, kp_svuid, kp_egid, kp_gid, kp_svgid, anonpid, kp.kp_proc.p_comm);
+        }
+
</ins><span class="cx">         switch (kp.kp_eproc.e_ppid) {
</span><span class="cx">         case 0:
</span><span class="cx">                 /* the kernel */
</span><span class="lines">@@ -1081,13 +1097,18 @@
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (jp &amp;&amp; !jp-&gt;anonymous &amp;&amp; !(kp.kp_proc.p_flag &amp; P_EXEC)) {
+                job_log(jp, LOG_APPLEONLY, &quot;Performance and sanity: fork() without exec*(). Please switch to posix_spawn()&quot;);
+        }
+
+
</ins><span class="cx">         /* A total hack: Normally, job_new() returns an error during shutdown, but anonymous jobs are special. */
</span><span class="cx">         if ((shutdown_state = jm-&gt;shutting_down)) {
</span><span class="cx">                 jm-&gt;shutting_down = false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (jobmgr_assumes(jm, (jr = job_new(jm, AUTO_PICK_LEGACY_LABEL, zombie ? zombie : kp.kp_proc.p_comm, NULL)) != NULL)) {
-                u_int proc_fflags = NOTE_EXEC|NOTE_EXIT /* |NOTE_REAP */;
</del><ins>+        if (jobmgr_assumes(jm, (jr = job_new(jm, AUTO_PICK_LEGACY_LABEL, kp.kp_proc.p_comm, NULL)) != NULL)) {
+                u_int proc_fflags = NOTE_EXEC|NOTE_FORK|NOTE_EXIT /* |NOTE_REAP */;
</ins><span class="cx"> 
</span><span class="cx">                 total_anon_children++;
</span><span class="cx">                 jr-&gt;anonymous = true;
</span><span class="lines">@@ -1107,7 +1128,7 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 if (shutdown_state &amp;&amp; jm-&gt;hopefully_first_cnt == 0) {
</span><del>-                        job_log(jr, LOG_APPLEONLY, &quot;This process showed up to the party while all the guests were leaving. Odds are that it will have a miserable time&quot;);
</del><ins>+                        job_log(jr, LOG_APPLEONLY, &quot;This process showed up to the party while all the guests were leaving. Odds are that it will have a miserable time.&quot;);
</ins><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 job_log(jr, LOG_DEBUG, &quot;Created PID %u anonymously by PPID %u%s%s&quot;, anonpid, kp.kp_eproc.e_ppid, jp ? &quot;: &quot; : &quot;&quot;, jp ? jp-&gt;label : &quot;&quot;);
</span><span class="lines">@@ -2044,7 +2065,7 @@
</span><span class="cx">                 j-&gt;weird_bootstrap = false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (j-&gt;log_redirect_fd &amp;&amp; !j-&gt;wait4pipe_eof) {
</del><ins>+        if (j-&gt;log_redirect_fd &amp;&amp; !j-&gt;legacy_LS_job) {
</ins><span class="cx">                 job_assumes(j, runtime_close(j-&gt;log_redirect_fd) != -1);
</span><span class="cx">                 j-&gt;log_redirect_fd = 0;
</span><span class="cx">         }
</span><span class="lines">@@ -2292,28 +2313,73 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void
</span><ins>+job_log_chidren_without_exec(job_t j)
+{
+        int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
+        size_t i, kp_cnt, len = 10*1024*1024;
+        struct kinfo_proc *kp;
+
+        if (j-&gt;anonymous || j-&gt;per_user) {
+                return;
+        }
+
+        if (!job_assumes(j, (kp = malloc(len)) != NULL)) {
+                return;
+        }
+        if (!job_assumes(j, sysctl(mib, 3, kp, &amp;len, NULL, 0) != -1)) {
+                goto out;
+        }
+
+        kp_cnt = len / sizeof(struct kinfo_proc);
+
+        for (i = 0; i &lt; kp_cnt; i++) {
+                if (kp[i].kp_eproc.e_ppid != j-&gt;p) {
+                        continue;
+                } else if (kp[i].kp_proc.p_flag &amp; P_EXEC) {
+                        continue;
+                }
+
+                job_log(j, LOG_APPLEONLY, &quot;Performance and sanity: fork() without exec*(). Please switch to posix_spawn()&quot;);
+        }
+
+out:
+        free(kp);
+}
+
+void
</ins><span class="cx"> job_callback_proc(job_t j, int flags, int fflags)
</span><span class="cx"> {
</span><del>-        if ((fflags &amp; NOTE_EXEC) &amp;&amp; j-&gt;anonymous) {
-                int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, j-&gt;p };
-                struct kinfo_proc kp;
-                size_t len = sizeof(kp);
</del><ins>+        bool program_changed = false;
</ins><span class="cx"> 
</span><del>-                if (job_assumes(j, sysctl(mib, 4, &amp;kp, &amp;len, NULL, 0) != -1)) {
-                        char newlabel[1000];
</del><ins>+        if (fflags &amp; NOTE_EXEC) {
+                program_changed = true;
</ins><span class="cx"> 
</span><del>-                        snprintf(newlabel, sizeof(newlabel), &quot;%p.%s&quot;, j, kp.kp_proc.p_comm);
</del><ins>+                if (j-&gt;anonymous) {
+                        int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, j-&gt;p };
+                        struct kinfo_proc kp;
+                        size_t len = sizeof(kp);
</ins><span class="cx"> 
</span><del>-                        job_log(j, LOG_DEBUG, &quot;Program changed. Updating the label to: %s&quot;, newlabel);
</del><ins>+                        if (job_assumes(j, sysctl(mib, 4, &amp;kp, &amp;len, NULL, 0) != -1) &amp;&amp; job_assumes(j, len == sizeof(kp))) {
+                                char newlabel[1000];
</ins><span class="cx"> 
</span><del>-                        LIST_REMOVE(j, label_hash_sle);
-                        strcpy((char *)j-&gt;label, newlabel);
-                        LIST_INSERT_HEAD(&amp;label_hash[hash_label(j-&gt;label)], j, label_hash_sle);
</del><ins>+                                snprintf(newlabel, sizeof(newlabel), &quot;%p.%s&quot;, j, kp.kp_proc.p_comm);
+
+                                job_log(j, LOG_INFO, &quot;Program changed. Updating the label to: %s&quot;, newlabel);
+                                j-&gt;lastlookup = NULL;
+                                j-&gt;lastlookup_gennum = 0;
+
+                                LIST_REMOVE(j, label_hash_sle);
+                                strcpy((char *)j-&gt;label, newlabel);
+                                LIST_INSERT_HEAD(&amp;label_hash[hash_label(j-&gt;label)], j, label_hash_sle);
+                        }
+                } else {
+                        job_log(j, LOG_DEBUG, &quot;Program changed&quot;);
</ins><span class="cx">                 }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (fflags &amp; NOTE_FORK) {
</span><del>-                job_log(j, LOG_DEBUG, &quot;Called fork()&quot;);
</del><ins>+                job_log(j, LOG_DEBUG, &quot;fork()ed%s&quot;, program_changed ? &quot;. For this message only: We don't know whether this event happened before or after execve().&quot; : &quot;&quot;);
+                job_log_chidren_without_exec(j);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (fflags &amp; NOTE_EXIT) {
</span><span class="lines">@@ -2467,7 +2533,7 @@
</span><span class="cx">         char nbuf[64];
</span><span class="cx">         pid_t c;
</span><span class="cx">         bool sipc = false;
</span><del>-        u_int proc_fflags = /* NOTE_EXEC|NOTE_FORK| */ NOTE_EXIT /* |NOTE_REAP */;
</del><ins>+        u_int proc_fflags = NOTE_EXIT|NOTE_FORK|NOTE_EXEC /* NOTE_REAP */;
</ins><span class="cx"> 
</span><span class="cx">         if (!job_assumes(j, j-&gt;mgr != NULL)) {
</span><span class="cx">                 return;
</span><span class="lines">@@ -2762,7 +2828,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void
</span><del>-job_find_and_blame_pids_with_weird_uids(job_t j)
</del><ins>+job_log_pids_with_weird_uids(job_t j)
</ins><span class="cx"> {
</span><span class="cx">         int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
</span><span class="cx">         size_t i, kp_cnt, len = 10*1024*1024;
</span><span class="lines">@@ -2834,7 +2900,7 @@
</span><span class="cx">         } else if (j-&gt;mach_uid) {
</span><span class="cx">                 if ((pwe = getpwuid(j-&gt;mach_uid)) == NULL) {
</span><span class="cx">                         job_log(j, LOG_ERR, &quot;getpwuid(\&quot;%u\&quot;) failed&quot;, j-&gt;mach_uid);
</span><del>-                        job_find_and_blame_pids_with_weird_uids(j);
</del><ins>+                        job_log_pids_with_weird_uids(j);
</ins><span class="cx">                         _exit(EXIT_FAILURE);
</span><span class="cx">                 }
</span><span class="cx">         } else {
</span><span class="lines">@@ -3750,10 +3816,8 @@
</span><span class="cx"> bool
</span><span class="cx"> job_useless(job_t j)
</span><span class="cx"> {
</span><del>-        /* Yes, j-&gt;unload_at_exit and j-&gt;only_once seem the same, but they'll differ someday... */
-
-        if ((j-&gt;unload_at_exit || j-&gt;only_once) &amp;&amp; j-&gt;start_time != 0) {
-                if (j-&gt;unload_at_exit &amp;&amp; j-&gt;j_port) {
</del><ins>+        if ((j-&gt;legacy_LS_job || j-&gt;only_once) &amp;&amp; j-&gt;start_time != 0) {
+                if (j-&gt;legacy_LS_job &amp;&amp; j-&gt;j_port) {
</ins><span class="cx">                         return false;
</span><span class="cx">                 }
</span><span class="cx">                 job_log(j, LOG_INFO, &quot;Exited. Was only configured to run once.&quot;);
</span><span class="lines">@@ -3916,7 +3980,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (j-&gt;log_redirect_fd) {
</span><del>-                if (job_assumes(j, j-&gt;wait4pipe_eof)) {
</del><ins>+                if (job_assumes(j, j-&gt;legacy_LS_job)) {
</ins><span class="cx">                         return &quot;Standard out/error is still valid&quot;;
</span><span class="cx">                 } else {
</span><span class="cx">                         job_assumes(j, runtime_close(j-&gt;log_redirect_fd) != -1);
</span><span class="lines">@@ -3974,6 +4038,7 @@
</span><span class="cx"> 
</span><span class="cx">         strcpy((char *)ms-&gt;name, name);
</span><span class="cx">         ms-&gt;job = j;
</span><ins>+        ms-&gt;gen_num = 1;
</ins><span class="cx">         ms-&gt;per_pid = pid_local;
</span><span class="cx"> 
</span><span class="cx">         if (*serviceport == MACH_PORT_NULL) {
</span><span class="lines">@@ -5725,9 +5790,9 @@
</span><span class="cx"> 
</span><span class="cx">         runtime_get_caller_creds(&amp;ldc);
</span><span class="cx"> 
</span><del>-#if 0
-        job_log(j, LOG_APPLEONLY, &quot;bootstrap_register() is deprecated. Service: %s&quot;, servicename);
-#endif
</del><ins>+        if (!(flags &amp; BOOTSTRAP_PER_PID_SERVICE) &amp;&amp; !j-&gt;legacy_LS_job) {
+                job_log(j, LOG_APPLEONLY, &quot;Performance: bootstrap_register() is deprecated. Service: %s&quot;, servicename);
+        }
</ins><span class="cx"> 
</span><span class="cx">         job_log(j, LOG_DEBUG, &quot;%sMach service registration attempt: %s&quot;, flags &amp; BOOTSTRAP_PER_PID_SERVICE ? &quot;Per PID &quot; : &quot;&quot;, servicename);
</span><span class="cx"> 
</span><span class="lines">@@ -5806,17 +5871,16 @@
</span><span class="cx">         if (ms) {
</span><span class="cx">                 launchd_assumes(machservice_port(ms) != MACH_PORT_NULL);
</span><span class="cx">                 job_log(j, LOG_DEBUG, &quot;%sMach service lookup: %s&quot;, flags &amp; BOOTSTRAP_PER_PID_SERVICE ? &quot;Per PID &quot; : &quot;&quot;, servicename);
</span><del>-#if 0
-                /* After Leopard ships, we should enable this */
</del><ins>+
</ins><span class="cx">                 if (j-&gt;lastlookup == ms &amp;&amp; j-&gt;lastlookup_gennum == ms-&gt;gen_num &amp;&amp; !j-&gt;per_user) {
</span><del>-                        ms-&gt;bad_perf_cnt++;
-                        job_log(j, LOG_APPLEONLY, &quot;Performance opportunity: Number of bootstrap_lookup(... \&quot;%s\&quot; ...) calls that should have been cached: %llu&quot;,
-                                        servicename, ms-&gt;bad_perf_cnt);
</del><ins>+                        job_log(ms-&gt;job, LOG_APPLEONLY, &quot;Performance: Please fix the framework to cache the Mach port for service: %s&quot;, servicename);
</ins><span class="cx">                 }
</span><ins>+
</ins><span class="cx">                 j-&gt;lastlookup = ms;
</span><span class="cx">                 j-&gt;lastlookup_gennum = ms-&gt;gen_num;
</span><del>-#endif
</del><ins>+
</ins><span class="cx">                 *serviceportp = machservice_port(ms);
</span><ins>+
</ins><span class="cx">                 kr = BOOTSTRAP_SUCCESS;
</span><span class="cx">         } else if (!(flags &amp; BOOTSTRAP_PER_PID_SERVICE) &amp;&amp; (inherited_bootstrap_port != MACH_PORT_NULL)) {
</span><span class="cx">                 job_log(j, LOG_DEBUG, &quot;Mach service lookup forwarded: %s&quot;, servicename);
</span><span class="lines">@@ -6469,8 +6533,7 @@
</span><span class="cx">                 jr-&gt;mach_uid = ldc.uid;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        jr-&gt;unload_at_exit = true;
-        jr-&gt;wait4pipe_eof = true;
</del><ins>+        jr-&gt;legacy_LS_job = true;
</ins><span class="cx">         jr-&gt;abandon_pg = true;
</span><span class="cx">         jr-&gt;stall_before_exec = jr-&gt;wait4debugger;
</span><span class="cx">         jr-&gt;wait4debugger = false;
</span></span></pre></div>
<a id="trunklaunchdsrclaunchd_runtimec"></a>
<div class="modfile"><h4>Modified: trunk/launchd/src/launchd_runtime.c (23445 => 23446)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/launchd/src/launchd_runtime.c        2007-10-23 15:47:01 UTC (rev 23445)
+++ trunk/launchd/src/launchd_runtime.c        2007-10-23 20:37:23 UTC (rev 23446)
</span><span class="lines">@@ -1173,22 +1173,23 @@
</span><span class="cx">         char newmsg[10000];
</span><span class="cx">         size_t i, j;
</span><span class="cx"> 
</span><del>-        if (!(LOG_MASK(attr-&gt;priority) &amp; internal_mask_pri)) {
-                goto out;
-        }
-
</del><span class="cx">         if (apple_internal_logging == 1) {
</span><span class="cx">                 apple_internal_logging = stat(&quot;/AppleInternal&quot;, &amp;sb);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (attr-&gt;priority == LOG_APPLEONLY) {
+                if (apple_internal_logging == 0) {
+                        attr-&gt;priority = LOG_NOTICE;
+                } else {
+                        return;
+                }
+        }
</ins><span class="cx"> 
</span><ins>+        if (!(LOG_MASK(attr-&gt;priority) &amp; internal_mask_pri)) {
+                goto out;
+        }
+
</ins><span class="cx">         if (!(debug_shutdown_hangs &amp;&amp; getpid() == 1)) {
</span><del>-                if (attr-&gt;priority == LOG_APPLEONLY) {
-                        if (apple_internal_logging == -1) {
-                                goto out;
-                        }
-                        attr-&gt;priority = LOG_NOTICE;
-                }
</del><span class="cx">                 vsnprintf(newmsg, sizeof(newmsg), message, args);
</span><span class="cx">                 logmsg_add(attr, saved_errno, newmsg);
</span><span class="cx">                 goto out;
</span></span></pre>
</div>
</div>

</body>
</html>