~n3npq/lsb/distribution-checker

« back to all changes in this revision

Viewing changes to utils/stop_server.pl

  • Committer: biga
  • Date: 2009-04-24 14:16:44 UTC
  • Revision ID: biga@spidey.linux-foundation.org-20090424141644-7evzd6mjocix7e68
init

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl -w
 
2
 
 
3
# LSB Test Execution Framework
 
4
# Stop Process Tree Module (stop_server.pl)
 
5
#
 
6
# Copyright (C) 2007-2009 The Linux Foundation. All rights reserved.
 
7
#
 
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
 
11
#
 
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.
 
15
#
 
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.
 
20
#
 
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
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
 
25
 
 
26
use FindBin;
 
27
 
 
28
sub BEGIN { unshift @INC, $FindBin::Bin; }
 
29
 
 
30
use Common;
 
31
 
 
32
my $server_pid = shift;
 
33
if (!$server_pid) {
 
34
        die "Usage: $0 <SERVER_PID>\n";
 
35
}
 
36
 
 
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.
 
39
my @tef_list = ();
 
40
my %children = ();
 
41
my %parent = ();
 
42
my %cmd_line = ();
 
43
 
 
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$!";
 
47
        return 0;
 
48
}
 
49
my @all_pids = grep(/^\d+$/, readdir(PROC_DIR));
 
50
closedir(PROC_DIR);
 
51
 
 
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>;
 
56
                close(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>;
 
61
                                close(CMDLINE_FILE);
 
62
                                if ($line) {
 
63
                                        $cmdline = $line;
 
64
                                }
 
65
                        }
 
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/)) {
 
69
                                push @tef_list, $pid;
 
70
                        }
 
71
                        $parent{$pid} = $ppid;
 
72
                        if (!defined($children{$ppid})) {
 
73
                                $children{$ppid} = [];
 
74
                        }
 
75
                        push @{$children{$ppid}}, $pid;
 
76
                }
 
77
        }
 
78
}
 
79
 
 
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
 
82
# back to browser.
 
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
 
87
                $this_parent_pid = 0;
 
88
                last;
 
89
        }
 
90
        else {
 
91
                $this_parent_pid = $parent{$this_parent_pid};
 
92
        }
 
93
}
 
94
 
 
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, $_;
 
107
                }
 
108
        }
 
109
}
 
110
 
 
111
# Send TERM signal to all processes
 
112
foreach (@tef_list, @server_list) {
 
113
        kill('SIGTERM', $_);
 
114
}
 
115
 
 
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{$_};
 
123
                }
 
124
        }
 
125
        if (scalar(keys %death_check) == 0) {
 
126
                last;
 
127
        }
 
128
        else {
 
129
                select(undef, undef, undef, 0.3);
 
130
        }
 
131
}
 
132
 
 
133
# Finalization: report about processes that were not killed (if any), and exit
 
134
if (scalar(keys %death_check) == 0) {
 
135
        exit 0;
 
136
}
 
137
else {
 
138
        print STDERR "Could not terminate processes: ".join(", ", sort keys %death_check)."\n";
 
139
        exit 1;
 
140
}