Revision: 23881 http://trac.macosforge.org/projects/launchd/changeset/23881 Author: dsorresso@apple.com Date: 2009-04-02 18:36:18 -0700 (Thu, 02 Apr 2009) Log Message: ----------- <rdar://problem/6745714> launchd mis-identifies stray processes for termination at shutdown Modified Paths: -------------- trunk/launchd/src/launch.h trunk/launchd/src/launchd_core_logic.c Modified: trunk/launchd/src/launch.h =================================================================== --- trunk/launchd/src/launch.h 2009-04-03 01:35:19 UTC (rev 23880) +++ trunk/launchd/src/launch.h 2009-04-03 01:36:18 UTC (rev 23881) @@ -100,6 +100,7 @@ #define LAUNCH_JOBKEY_THROTTLEINTERVAL "ThrottleInterval" #define LAUNCH_JOBKEY_LAUNCHONLYONCE "LaunchOnlyOnce" #define LAUNCH_JOBKEY_ABANDONPROCESSGROUP "AbandonProcessGroup" +#define LAUNCH_JOBKEY_IGNOREPROCESSGROUPATSHUTDOWN "IgnoreProcessGroupAtShutdown" #define LAUNCH_JOBKEY_POLICIES "Policies" #define LAUNCH_JOBKEY_ENABLETRANSACTIONS "EnableTransactions" Modified: trunk/launchd/src/launchd_core_logic.c =================================================================== --- trunk/launchd/src/launchd_core_logic.c 2009-04-03 01:35:19 UTC (rev 23880) +++ trunk/launchd/src/launchd_core_logic.c 2009-04-03 01:36:18 UTC (rev 23881) @@ -510,6 +510,7 @@ deny_unknown_mslookups :1, /* A flag for changing the behavior of bootstrap_look_up() */ unload_at_mig_return :1, /* A job thoroughly confused launchd. We need to unload it ASAP */ abandon_pg :1, /* man launchd.plist --> AbandonProcessGroup */ + ignore_pg_at_shutdown :1, /* During shutdown, do not send SIGTERM to stray processes in the process group of this job. */ poll_for_vfs_changes :1, /* a hack to work around the fact that kqueues don't work on all filesystems */ deny_job_creation :1, /* Don't let this job create new 'job_t' objects in launchd */ kill_via_shmem :1, /* man launchd.plist --> EnableTransactions */ @@ -1690,6 +1691,9 @@ } j->no_init_groups = !value; found_key = true; + } else if( strcasecmp(key, LAUNCH_JOBKEY_IGNOREPROCESSGROUPATSHUTDOWN) == 0 ) { + j->ignore_pg_at_shutdown = value; + found_key = true; } break; case 'r': @@ -5693,7 +5697,7 @@ /* 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_INFO | LOG_CONSOLE, "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_log(jm, LOG_INFO | LOG_CONSOLE, "Stray %s%s at shutdown: PID %u PPID %u PGID %u %s", z, j ? "anonymous job" : "process", p_i, pp_i, pg_i, n); int status = 0; if( pp_i == getpid() && !jobmgr_assumes(jm, kp[i].kp_proc.p_stat != SZOMB) ) { @@ -5702,7 +5706,17 @@ } kp_skipped++; } else { - ps[i] = p_i; + job_t leader = jobmgr_find_by_pid(jm, pg_i, false); + /* See rdar://problem/6745714. Some jobs have child processes that back kernel state, + * so we don't want to terminate them. Long-term, I'd really like to provide shutdown + * hints to the kernel along the way, so that it could shutdown certain subsystems when + * their userspace emissaries go away, before the call to reboot(2). + */ + if( leader && leader->ignore_pg_at_shutdown ) { + kp_skipped++; + } else { + ps[i] = p_i; + } } } else { kp_skipped++;