#! /bin/sh ### BEGIN INIT INFO # Provides: sendsigs # Required-Start: # Required-Stop: umountnfs # Default-Start: # Default-Stop: 0 6 # Short-Description: Kill all remaining processes. # Description: ### END INIT INFO global PATH := '/sbin:/usr/sbin:/bin:/usr/bin' source /lib/lsb/init-functions # Make it possible to see who the misbehaving processes are proc report_unkillable { test -x /usr/share/apport/unkillable_shutdown || return if test ! -e /etc/default/apport || ! grep -q '^enabled[[:space:]]*=[[:space:]]*1' /etc/default/apport { return } /usr/share/apport/unkillable_shutdown $OMITPIDS } proc upstart_killed_jobs { initctl list | grep 'stop/killed' } proc upstart_jobs { initctl list | grep -E '(start/|stop/killed)' | sed -n -e "/process [0-9]/s/.*process //p" } proc do_stop { global OMITPIDS := '' for omitfile in [/run/sendsigs.omit] { if test -e $omitfile { for pid in [$[cat $omitfile]] { global OMITPIDS := ""$(OMITPIDS:+$OMITPIDS )-o $pid"" } } } # Load sendsigs.omit.d/packagename files too, to make it # possible for scripts that need to modify the list of pids at # run time without race conditions. for omitdir in [/run/sendsigs.omit.d] { if test -d $(omitdir) { for pidfile in ["$(omitdir)/"*] { test -f $pidfile || continue for pid in [$[cat $pidfile]] { global OMITPIDS := ""$(OMITPIDS:+$OMITPIDS )-o $pid"" } } } } # Upstart jobs have their own "stop on" clauses that sends # SIGTERM/SIGKILL just like this, so if they're still running, # they're supposed to be if test -x /sbin/initctl { for pid in [$[upstart_jobs]] { global OMITPIDS := ""$(OMITPIDS:+$OMITPIDS )-o $pid"" } } # Flush the kernel I/O buffer before we start to kill # processes, to make sure the IO of already stopped services to # not slow down the remaining processes to a point where they # are accidentily killed with SIGKILL because they did not # manage to shut down in time. sync # Kill all processes. log_action_begin_msg "Asking all remaining processes to terminate" killall5 -15 $OMITPIDS # SIGTERM log_action_end_msg 0 global alldead := ''"" global OMITPIDS0 := $OMITPIDS for seq in [1 2 3 4 5 6 7 8 9 10] { global OMITPIDS := $OMITPIDS0 # use SIGCONT/signal 18 to check if there are # processes left. No need to check the exit code # value, because either killall5 work and it make # sense to wait for processes to die, or it fail and # there is nothing to wait for. # did an upstart job start since we last polled initctl? check # again on each loop and add any new jobs (e.g., plymouth) to # the list. If we did miss one starting up, this beats waiting # 10 seconds before shutting down. if test -x /sbin/initctl { for pid in [$[upstart_jobs]] { global OMITPIDS := ""$(OMITPIDS:+$OMITPIDS )-o $pid"" } } if killall5 -18 $OMITPIDS { : } else { global alldead := '1' break } sleep 1 } # Upstart has a method to set a kill timeout and so the job author # may want us to wait longer than 10 seconds (as in the case of # mysql). (LP: #688541) # # We will wait up to 300 seconds for any jobs in stop/killed state. # Any kill timeout higher than that will be overridden by the need # to shutdown. NOTE the re-use of seq from above, since we already # waited up to 10 seconds for them. while [ -n "$(upstart_killed_jobs)" ] { global seq := $($seq+1) if test $seq -ge 300 { break } sleep 1 } if test -z $alldead { #report_unkillable log_action_begin_msg "Killing all remaining processes" killall5 -9 $OMITPIDS # SIGKILL log_action_end_msg 1 } else { log_action_begin_msg "All processes ended within $seq seconds" log_action_end_msg 0 } } matchstr $1 { start|status { # No-op } restart|reload|force-reload { echo "Error: argument '$1' not supported" > !2 exit 3 } stop { do_stop } * { echo "Usage: $0 start|stop" > !2 exit 3 } } : (CommandList children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:PATH) op: Equal rhs: {(/sbin) (Lit_Other ":") (/usr/sbin) (Lit_Other ":") (/bin) (Lit_Other ":") (/usr/bin)} spids: [31] ) ] spids: [31] ) (C {(.)} {(/lib/lsb/init-functions)}) (FuncDef name: report_unkillable body: (BraceGroup children: [ (AndOr children: [ (C {(Lit_Other "[")} {(-x)} {(/usr/share/apport/unkillable_shutdown)} {(Lit_Other "]")}) (ControlFlow token:) ] op_id: Op_DPipe ) (If arms: [ (if_arm cond: [ (Sentence child: (AndOr children: [ (C {(Lit_Other "[")} {(KW_Bang "!")} {(-e)} {(/etc/default/apport)} {(Lit_Other "]")} ) (Pipeline children: [ (C {(grep)} {(-q)} {(SQ <"^enabled[[:space:]]*=[[:space:]]*1">)} {(/etc/default/apport)} ) ] negated: True ) ] op_id: Op_DPipe ) terminator: ) ] action: [(ControlFlow token:)] spids: [-1 96] ) ] spids: [-1 102] ) (C {(/usr/share/apport/unkillable_shutdown)} {($ VSub_Name "$OMITPIDS")}) ] spids: [53] ) spids: [49 52] ) (FuncDef name: upstart_killed_jobs body: (BraceGroup children: [ (Pipeline children: [(C {(initctl)} {(list)}) (C {(grep)} {(SQ )})] negated: False ) ] spids: [117] ) spids: [112 116] ) (FuncDef name: upstart_jobs body: (BraceGroup children: [ (Pipeline children: [ (C {(initctl)} {(list)}) (C {(grep)} {(-E)} {(SQ <"(start/|stop/killed)">)}) (C {(sed)} {(-n)} {(-e)} {(DQ ("/process [0-9]/s/.*process //p"))}) ] negated: False ) ] spids: [140] ) spids: [135 139] ) (FuncDef name: do_stop body: (BraceGroup children: [ (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:OMITPIDS) op:Equal rhs:{(SQ )} spids:[180])] spids: [180] ) (ForEach iter_name: omitfile iter_words: [{(/run/sendsigs.omit)}] do_arg_iter: False body: (DoGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-e)} {($ VSub_Name "$omitfile")} {(Lit_Other "]")}) terminator: ) ] action: [ (ForEach iter_name: pid iter_words: [ { (CommandSubPart command_list: (CommandList children: [(C {(cat)} {($ VSub_Name "$omitfile")})] ) left_token: spids: [216 220] ) } ] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OMITPIDS) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonPlus arg_word: {($ VSub_Name "$OMITPIDS") (" ")} ) spids: [228 233] ) ("-o ") ($ VSub_Name "$pid") ) } spids: [226] ) ] spids: [226] ) ] spids: [223 239] ) spids: [215 221] ) ] spids: [-1 207] ) ] spids: [-1 242] ) ] spids: [193 245] ) spids: [189 191] ) (ForEach iter_name: omitdir iter_words: [{(/run/sendsigs.omit.d)}] do_arg_iter: False body: (DoGroup children: [ (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-d)} {(DQ (${ VSub_Name omitdir))} {(Lit_Other "]")} ) terminator: ) ] action: [ (ForEach iter_name: pidfile iter_words: [{(DQ (${ VSub_Name omitdir) (/)) (Lit_Other "*")}] do_arg_iter: False body: (DoGroup children: [ (AndOr children: [ (C {(Lit_Other "[")} {(-f)} {(DQ ($ VSub_Name "$pidfile"))} {(Lit_Other "]")} ) (ControlFlow token: ) ] op_id: Op_DPipe ) (ForEach iter_name: pid iter_words: [ { (CommandSubPart command_list: (CommandList children: [(C {(cat)} {($ VSub_Name "$pidfile")})] ) left_token: spids: [330 334] ) } ] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OMITPIDS) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonPlus arg_word: {($ VSub_Name "$OMITPIDS") (" ")} ) spids: [342 347] ) ("-o ") ($ VSub_Name "$pid") ) } spids: [340] ) ] spids: [340] ) ] spids: [337 353] ) spids: [329 335] ) ] spids: [306 356] ) spids: [296 304] ) ] spids: [-1 288] ) ] spids: [-1 359] ) ] spids: [270 362] ) spids: [266 268] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-x)} {(/sbin/initctl)} {(Lit_Other "]")}) terminator: ) ] action: [ (ForEach iter_name: pid iter_words: [ { (CommandSubPart command_list: (CommandList children:[(C {(upstart_jobs)})]) left_token: spids: [398 400] ) } ] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OMITPIDS) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonPlus arg_word: {($ VSub_Name "$OMITPIDS") (" ")} ) spids: [408 413] ) ("-o ") ($ VSub_Name "$pid") ) } spids: [406] ) ] spids: [406] ) ] spids: [403 419] ) spids: [397 401] ) ] spids: [-1 389] ) ] spids: [-1 422] ) (C {(sync)}) (C {(log_action_begin_msg)} {(DQ ("Asking all remaining processes to terminate"))}) (C {(killall5)} {(-15)} {($ VSub_Name "$OMITPIDS")}) (C {(log_action_end_msg)} {(0)}) (Assignment keyword: Assign_None pairs: [(assign_pair lhs:(LhsName name:alldead) op:Equal rhs:{(DQ )} spids:[476])] spids: [476] ) (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OMITPIDS0) op: Equal rhs: {(DQ ($ VSub_Name "$OMITPIDS"))} spids: [481] ) ] spids: [481] ) (ForEach iter_name: seq iter_words: [{(1)} {(2)} {(3)} {(4)} {(5)} {(6)} {(7)} {(8)} {(9)} {(10)}] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OMITPIDS) op: Equal rhs: {(DQ ($ VSub_Name "$OMITPIDS0"))} spids: [517] ) ] spids: [517] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-x)} {(/sbin/initctl)} {(Lit_Other "]")}) terminator: ) ] action: [ (ForEach iter_name: pid iter_words: [ { (CommandSubPart command_list: (CommandList children:[(C {(upstart_jobs)})]) left_token: spids: [580 582] ) } ] do_arg_iter: False body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:OMITPIDS) op: Equal rhs: { (DQ (BracedVarSub token: suffix_op: (StringUnary op_id: VTest_ColonPlus arg_word: {($ VSub_Name "$OMITPIDS") (" ")} ) spids: [590 595] ) ("-o ") ($ VSub_Name "$pid") ) } spids: [588] ) ] spids: [588] ) ] spids: [585 601] ) spids: [579 583] ) ] spids: [-1 571] ) ] spids: [-1 604] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(killall5)} {(-18)} {($ VSub_Name "$OMITPIDS")}) terminator: ) ] action: [(C {(Lit_Other ":")})] spids: [-1 617] ) ] else_action: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:alldead) op: Equal rhs: {(1)} spids: [626] ) ] spids: [626] ) (ControlFlow token:) ] spids: [623 633] ) (C {(sleep)} {(1)}) ] spids: [514 642] ) spids: [492 512] ) (While cond: [ (Sentence child: (C {(Lit_Other "[")} {(-n)} { (DQ (CommandSubPart command_list: (CommandList children:[(C {(upstart_killed_jobs)})]) left_token: spids: [685 687] ) ) } {(Lit_Other "]")} ) terminator: ) ] body: (DoGroup children: [ (Assignment keyword: Assign_None pairs: [ (assign_pair lhs: (LhsName name:seq) op: Equal rhs: { (ArithSubPart anode: (ArithBinary op_id: Arith_Plus left: (ArithWord w:{($ VSub_Name "$seq")}) right: (ArithWord w:{(Lit_Digits 1)}) ) spids: [698 703] ) } spids: [697] ) ] spids: [697] ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {($ VSub_Name "$seq")} {(-ge)} {(300)} {(Lit_Other "]")} ) terminator: ) ] action: [(ControlFlow token:)] spids: [-1 720] ) ] spids: [-1 726] ) (C {(sleep)} {(1)}) ] spids: [694 736] ) ) (If arms: [ (if_arm cond: [ (Sentence child: (C {(Lit_Other "[")} {(-z)} {(DQ ($ VSub_Name "$alldead"))} {(Lit_Other "]")}) terminator: ) ] action: [ (C {(log_action_begin_msg)} {(DQ ("Killing all remaining processes"))}) (C {(killall5)} {(-9)} {($ VSub_Name "$OMITPIDS")}) (C {(log_action_end_msg)} {(1)}) ] spids: [-1 754] ) ] else_action: [ (C {(log_action_begin_msg)} {(DQ ("All processes ended within ") ($ VSub_Name "$seq") (" seconds"))} ) (C {(log_action_end_msg)} {(0)}) ] spids: [783 800] ) ] spids: [177] ) spids: [172 176] ) (Case to_match: {(DQ ($ VSub_Number "$1"))} arms: [ (case_arm pat_list:[{(start)}{(status)}] spids:[814817824-1]) (case_arm pat_list: [{(restart)} {(reload)} {(force-reload)}] action: [ (SimpleCommand words: [{(echo)} {(DQ ("Error: argument '") ($ VSub_Number "$1") ("' not supported"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[843])] ) (C {(exit)} {(3)}) ] spids: [827 832 852 -1] ) (case_arm pat_list:[{(stop)}] action:[(C {(do_stop)})] spids:[855856862-1]) (case_arm pat_list: [{(Lit_Other "*")}] action: [ (SimpleCommand words: [{(echo)} {(DQ ("Usage: ") ($ VSub_Number "$0") (" start|stop"))}] redirects: [(Redir op_id:Redir_GreatAnd fd:-1 arg_word:{(2)} spids:[877])] ) (C {(exit)} {(3)}) ] spids: [865 866 886 -1] ) ] spids: [805 811 888] ) (C {(Lit_Other ":")}) ] )