stop.pl 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #!/usr/bin/perl -w
  2. #
  3. # Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
  4. # Copyright (C) 2001 Internet Software Consortium.
  5. #
  6. # Permission to use, copy, modify, and/or distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  11. # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  12. # AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  13. # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  14. # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  15. # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  16. # PERFORMANCE OF THIS SOFTWARE.
  17. # Framework for stopping test servers
  18. # Based on the type of server specified, signal the server to stop, wait
  19. # briefly for it to die, and then kill it if it is still alive.
  20. # If a server is specified, stop it. Otherwise, stop all servers for test.
  21. use strict;
  22. use Cwd 'abs_path';
  23. # Option handling
  24. # [--use-rndc] test [server]
  25. #
  26. # test - name of the test directory
  27. # server - name of the server directory
  28. my $usage = "usage: $0 [--use-rndc] test-directory [server-directory]";
  29. my $use_rndc;
  30. while (@ARGV && $ARGV[0] =~ /^-/) {
  31. my $opt = shift @ARGV;
  32. if ($opt eq '--use-rndc') {
  33. $use_rndc = 1;
  34. } else {
  35. die "$usage\n";
  36. }
  37. }
  38. my $test = $ARGV[0];
  39. my $server = $ARGV[1];
  40. my $errors = 0;
  41. die "$usage\n" unless defined($test);
  42. die "No test directory: \"$test\"\n" unless (-d $test);
  43. die "No server directory: \"$server\"\n" if (defined($server) && !-d "$test/$server");
  44. # Global variables
  45. my $testdir = abs_path($test);
  46. my @servers;
  47. # Determine which servers need to be stopped.
  48. if (defined $server) {
  49. @servers = ($server);
  50. } else {
  51. local *DIR;
  52. opendir DIR, $testdir or die "$testdir: $!\n";
  53. my @files = sort readdir DIR;
  54. closedir DIR;
  55. my @ns = grep /^nsx?[0-9]*$/, @files;
  56. my @lwresd = grep /^lwresd[0-9]*$/, @files;
  57. my @ans = grep /^ans[0-9]*$/, @files;
  58. push @servers, @ns, @lwresd, @ans;
  59. }
  60. # Stop the server(s), pass 1: rndc.
  61. if ($use_rndc) {
  62. foreach my $server (grep /^ns/, @servers) {
  63. stop_rndc($server);
  64. }
  65. wait_for_servers(30, grep /^ns/, @servers);
  66. }
  67. # Pass 2: SIGTERM
  68. foreach my $server (@servers) {
  69. stop_signal($server, "TERM");
  70. }
  71. wait_for_servers(60, @servers);
  72. # Pass 3: SIGABRT
  73. foreach my $server (@servers) {
  74. stop_signal($server, "ABRT");
  75. }
  76. exit($errors ? 1 : 0);
  77. # Subroutines
  78. # Return the full path to a given server's PID file.
  79. sub server_pid_file {
  80. my($server) = @_;
  81. my $pid_file;
  82. if ($server =~ /^nsx/) {
  83. $pid_file = "bind10.pid";
  84. } elsif ($server =~ /^ns/) {
  85. $pid_file = "named.pid";
  86. } elsif ($server =~ /^lwresd/) {
  87. $pid_file = "lwresd.pid";
  88. } elsif ($server =~ /^ans/) {
  89. $pid_file = "ans.pid";
  90. } else {
  91. print "I:Unknown server type $server\n";
  92. exit 1;
  93. }
  94. $pid_file = "$testdir/$server/$pid_file";
  95. }
  96. # Read a PID.
  97. sub read_pid {
  98. my($pid_file) = @_;
  99. local *FH;
  100. my $result = open FH, "< $pid_file";
  101. if (!$result) {
  102. print "I:$pid_file: $!\n";
  103. unlink $pid_file;
  104. return;
  105. }
  106. my $pid = <FH>;
  107. chomp($pid);
  108. return $pid;
  109. }
  110. # Stop a named process with rndc.
  111. sub stop_rndc {
  112. my($server) = @_;
  113. return unless ($server =~ /^ns(\d+)$/);
  114. my $ip = "10.53.0.$1";
  115. # Ugly, but should work.
  116. system("$ENV{RNDC} -c $testdir/../common/rndc.conf -s $ip -p 9953 stop | sed 's/^/I:$server /'");
  117. return;
  118. }
  119. # Stop a server by sending a signal to it.
  120. sub stop_signal {
  121. my($server, $sig) = @_;
  122. my $pid_file = server_pid_file($server);
  123. return unless -f $pid_file;
  124. my $pid = read_pid($pid_file);
  125. return unless defined($pid);
  126. if ($sig eq 'ABRT') {
  127. print "I:$server didn't die when sent a SIGTERM\n";
  128. $errors++;
  129. }
  130. my $result = kill $sig, $pid;
  131. if (!$result) {
  132. print "I:$server died before a SIG$sig was sent\n";
  133. unlink $pid_file;
  134. $errors++;
  135. }
  136. return;
  137. }
  138. sub wait_for_servers {
  139. my($timeout, @servers) = @_;
  140. my @pid_files = grep { defined($_) }
  141. map { server_pid_file($_) } @servers;
  142. while ($timeout > 0 && @pid_files > 0) {
  143. @pid_files = grep { -f $_ } @pid_files;
  144. sleep 1 if (@pid_files > 0);
  145. $timeout--;
  146. }
  147. return;
  148. }