@@ -1524,6 +1524,7 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
15241524 char * id = NULL , * env = NULL , * cgroup = NULL ;
15251525 char * pre_script = NULL , * post_script = NULL ;
15261526 char * ready_script = NULL , * conflict = NULL ;
1527+ char * cleanup_script = NULL ;
15271528 char ident [MAX_IDENT_LEN ];
15281529 char * ifstmt = NULL ;
15291530 char * notify = NULL ;
@@ -1630,6 +1631,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
16301631 post_script = arg ;
16311632 else if (MATCH_CMD (cmd , "ready:" , arg ))
16321633 ready_script = arg ;
1634+ else if (MATCH_CMD (cmd , "cleanup:" , arg ))
1635+ cleanup_script = arg ;
16331636 else if (MATCH_CMD (cmd , "env:" , arg ))
16341637 env = arg ;
16351638 /* catch both cgroup: and cgroup. handled in parse_cgroup() */
@@ -1817,6 +1820,11 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
18171820 parse_script (svc , "ready" , ready_script , & svc -> ready_tmo , svc -> ready_script , sizeof (svc -> ready_script ));
18181821 else
18191822 memset (svc -> ready_script , 0 , sizeof (svc -> ready_script ));
1823+ if (cleanup_script )
1824+ parse_script (svc , "cleanup" , cleanup_script , & svc -> cleanup_tmo , svc -> cleanup_script , sizeof (svc -> cleanup_script ));
1825+ else
1826+ memset (svc -> cleanup_script , 0 , sizeof (svc -> cleanup_script ));
1827+
18201828 if (!svc_is_tty (svc )) {
18211829 if (log )
18221830 parse_log (svc , log );
@@ -1916,8 +1924,8 @@ int service_register(int type, char *cfg, struct rlimit rlimit[], char *file)
19161924}
19171925
19181926/*
1919- * This function is called when cleaning up lingering (stopped) services
1920- * after a .conf reload .
1927+ * This function is called at the end of a runlevel change or reload
1928+ * command to delete all remnants of removed services .
19211929 *
19221930 * We need to ensure we properly stop the service before removing it,
19231931 * including stopping any pending restart or SIGKILL timers before we
@@ -1962,10 +1970,14 @@ void service_monitor(pid_t lost, int status)
19621970 /* If the setup phase fails, drive svc to crashed. */
19631971 svc -> status = status ;
19641972 /* fallthrough */
1973+ case SVC_TEARDOWN_STATE :
19651974 case SVC_CLEANUP_STATE :
19661975 dbg ("collected script %s(%d), normal exit: %d, signaled: %d, exit code: %d" ,
1967- svc -> state == SVC_CLEANUP_STATE ? svc -> post_script : svc -> pre_script ,
1968- lost , ok , sig , rc );
1976+ (svc -> state == SVC_TEARDOWN_STATE
1977+ ? svc -> post_script
1978+ : (svc -> state == SVC_CLEANUP_STATE
1979+ ? svc -> cleanup_script
1980+ : svc -> pre_script )), lost , ok , sig , rc );
19691981 /* Kill all children in the same proess group, e.g. logit */
19701982 dbg ("Killing lingering children in same process group ..." );
19711983 kill (- svc -> pid , SIGKILL );
@@ -2245,6 +2257,41 @@ void service_ready_script(svc_t *svc)
22452257 service_script_add (svc , pid , svc -> ready_tmo );
22462258}
22472259
2260+ static void service_cleanup_script (svc_t * svc )
2261+ {
2262+ svc -> pid = service_fork (svc );
2263+ if (svc -> pid < 0 ) {
2264+ err (1 , "Failed forking off %s cleanup:script %s" , svc_ident (svc , NULL , 0 ), svc -> cleanup_script );
2265+ return ;
2266+ }
2267+
2268+ if (svc -> pid == 0 ) {
2269+ char buf [CMD_SIZE ];
2270+ char * argv [4 ] = {
2271+ "sh" ,
2272+ "-ac" ,
2273+ buf ,
2274+ NULL
2275+ };
2276+ char * env_file ;
2277+
2278+ redirect (svc );
2279+
2280+ env_file = svc_getenv (svc );
2281+ if (env_file )
2282+ snprintf (buf , sizeof (buf ), ". %s; exec %s" , env_file , svc -> cleanup_script );
2283+ else
2284+ strlcpy (buf , svc -> cleanup_script , sizeof (buf ));
2285+
2286+ set_pre_post_envs (svc , "cleanup" );
2287+ execvp (_PATH_BSHELL , argv );
2288+ _exit (EX_OSERR );
2289+ }
2290+
2291+ dbg ("%s: cleanup:script %s started as PID %d" , svc_ident (svc , NULL , 0 ), svc -> cleanup_script , svc -> pid );
2292+ service_timeout_after (svc , svc -> cleanup_tmo , service_kill_script );
2293+ }
2294+
22482295static void service_retry (svc_t * svc )
22492296{
22502297 char * restart_cnt = (char * )& svc -> restart_cnt ;
@@ -2431,6 +2478,11 @@ int service_step(svc_t *svc)
24312478 condstr (cond_get_agg (svc -> cond )));
24322479
24332480 switch (svc -> state ) {
2481+ case SVC_CLEANUP_STATE :
2482+ if (!svc -> pid )
2483+ svc_set_state (svc , SVC_HALTED_STATE );
2484+ break ;
2485+
24342486 case SVC_HALTED_STATE :
24352487 if (enabled )
24362488 svc_set_state (svc , SVC_WAITING_STATE );
@@ -2469,7 +2521,7 @@ int service_step(svc_t *svc)
24692521 case SVC_TYPE_SYSV :
24702522 case SVC_TYPE_TTY :
24712523 if (svc_has_post (svc )) {
2472- svc_set_state (svc , SVC_CLEANUP_STATE );
2524+ svc_set_state (svc , SVC_TEARDOWN_STATE );
24732525 service_post_script (svc );
24742526 } else
24752527 svc_set_state (svc , SVC_HALTED_STATE );
@@ -2489,9 +2541,14 @@ int service_step(svc_t *svc)
24892541 }
24902542 break ;
24912543
2492- case SVC_CLEANUP_STATE :
2493- if (!svc -> pid )
2494- svc_set_state (svc , SVC_HALTED_STATE );
2544+ case SVC_TEARDOWN_STATE :
2545+ if (!svc -> pid ) {
2546+ if (svc_is_removed (svc ) && svc_has_cleanup (svc )) {
2547+ svc_set_state (svc , SVC_CLEANUP_STATE );
2548+ service_cleanup_script (svc );
2549+ } else
2550+ svc_set_state (svc , SVC_HALTED_STATE );
2551+ }
24952552 break ;
24962553
24972554 case SVC_SETUP_STATE :
0 commit comments