3
# LSB Test Execution Framework
4
# Stop Process Tree Module (stop_server.pl)
6
# Copyright (C) 2007-2009 The Linux Foundation. All rights reserved.
8
# This program has been developed by ISP RAS for LF.
9
# The ptyshell tool is originally written by Jiri Dluhos <jdluhos@suse.cz>
10
# Copyright (C) 2005-2007 SuSE Linux Products GmbH
12
# This program is free software; you can redistribute it and/or
13
# modify it under the terms of the GNU General Public License
14
# version 2 as published by the Free Software Foundation.
16
# This program is distributed in the hope that it will be useful,
17
# but WITHOUT ANY WARRANTY; without even the implied warranty of
18
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19
# GNU General Public License for more details.
21
# You should have received a copy of the GNU General Public License
22
# along with this program; if not, write to the Free Software
23
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
28
sub BEGIN { unshift @INC, $FindBin::Bin; }
32
my $server_pid = shift;
34
die "Usage: $0 <SERVER_PID>\n";
37
# Build the list of processes to be killed.
38
# Sub-tree of this particular process is excluded so that it could finish its work.
44
# Read list of all currently running processes
45
if (!opendir(PROC_DIR, '/proc')) {
46
print STDERR "Failed to open /proc directory for reading:\n$!";
49
my @all_pids = grep(/^\d+$/, readdir(PROC_DIR));
52
# Build the parent-child tree and get command lines
53
foreach my $pid (@all_pids) {
54
if (open(PID_FILE, "/proc/$pid/stat")) {
55
my $info = <PID_FILE>;
57
if ($info =~ m/^\d+\s+\((.*)\)\s+\S\s+(\d+)\s+[^\(\)]+$/) {
58
my ($cmdline, $ppid) = ($1, $2);
59
if (open(CMDLINE_FILE, "/proc/$pid/cmdline")) {
60
my $line = <CMDLINE_FILE>;
66
$cmd_line{$pid} = $cmdline;
67
# Add lsb-tef.pl, if it was started from Web-UI.
68
if (($cmdline =~ m/\blsb-tef\.pl\x00/) and ($cmdline =~ m/\x00--webui\x00/)) {
71
$parent{$pid} = $ppid;
72
if (!defined($children{$ppid})) {
73
$children{$ppid} = [];
75
push @{$children{$ppid}}, $pid;
80
# Find grand-parent of current process which is 'dtk-server.pl':
81
# we need to exclude it from killing, so that we could send response
83
my $this_parent_pid = $$;
84
while ($cmd_line{$this_parent_pid} !~ m/\bdtk-server\.pl\x00/) {
85
if (!$parent{$this_parent_pid}) {
86
# Did not find dtk-server.pl - started not from Web-UI
91
$this_parent_pid = $parent{$this_parent_pid};
95
# Get the plain list of processes to kill (breadth-first tree-walk)
96
my @server_list = ($server_pid);
97
for (my $i = 0; $i < scalar(@server_list); ++$i) {
98
my $pid = $server_list[$i];
99
if ($children{$pid}) {
100
foreach (@{$children{$pid}}) {
101
# Skip all lsb-tef.pl instances. Those started from command line should
102
# continue running, those started from Web-UI are in @tef_list already.
103
next if ($cmd_line{$_} =~ m/\blsb-tef\.pl\x00/);
104
# Also exclude Web-UI subtree of this process.
105
next if ($_ == $this_parent_pid);
106
push @server_list, $_;
111
# Send TERM signal to all processes
112
foreach (@tef_list, @server_list) {
116
# Try 20 times, waiting 0.3 seconds each time, for all the processes to be really dead.
117
# Check only server processes, because lsb-tef.pl is stopping too slowly.
118
my %death_check = map { $_ => 1 } @server_list;
119
for (my $i = 0; $i < 20; ++$i) {
120
foreach (keys %death_check) {
121
if (!is_process_running($_)) {
122
delete $death_check{$_};
125
if (scalar(keys %death_check) == 0) {
129
select(undef, undef, undef, 0.3);
133
# Finalization: report about processes that were not killed (if any), and exit
134
if (scalar(keys %death_check) == 0) {
138
print STDERR "Could not terminate processes: ".join(", ", sort keys %death_check)."\n";