Merge in build trunk.
[m6w6/libmemcached] / libtest / killpid.cc
1 /* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
2 *
3 * libtest
4 *
5 * Copyright (C) 2011 Data Differential, http://datadifferential.com/
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22
23 #include <libtest/common.h>
24
25 #include <cstdlib>
26 #include <cstring>
27 #include <iostream>
28 #include <sstream>
29 #include <signal.h>
30 #include <sys/types.h>
31 #include <sys/types.h>
32 #include <sys/wait.h>
33
34
35 #include <libtest/killpid.h>
36 #include <libtest/stream.h>
37
38 using namespace libtest;
39
40 bool kill_pid(pid_t pid_arg)
41 {
42 assert(pid_arg > 0);
43 if (pid_arg < 1)
44 {
45 Error << "Invalid pid:" << pid_arg;
46 return false;
47 }
48
49 if ((::kill(pid_arg, SIGTERM) == -1))
50 {
51 switch (errno)
52 {
53 case EPERM:
54 Error << "Does someone else have a process running locally for " << int(pid_arg) << "?";
55 return false;
56
57 case ESRCH:
58 Error << "Process " << int(pid_arg) << " not found.";
59 return false;
60
61 default:
62 case EINVAL:
63 Error << "kill() " << strerror(errno);
64 return false;
65 }
66 }
67
68 int status= 0;
69 if (waitpid(pid_arg, &status, 0) == -1)
70 {
71 switch (errno)
72 {
73 // Just means that the server has already gone away
74 case ECHILD:
75 {
76 return true;
77 }
78 }
79
80 Error << "Error occured while waitpid(" << strerror(errno) << ") on pid " << int(pid_arg);
81
82 return false;
83 }
84
85 return true;
86 }
87
88 bool check_pid(const std::string &filename)
89 {
90 if (filename.empty())
91 {
92 return false;
93 }
94
95 FILE *fp;
96 if ((fp= fopen(filename.c_str(), "r")))
97 {
98 char pid_buffer[1024];
99
100 char *ptr= fgets(pid_buffer, sizeof(pid_buffer), fp);
101 fclose(fp);
102
103 if (ptr)
104 {
105 pid_t pid= (pid_t)atoi(pid_buffer);
106 if (pid > 0)
107 {
108 return (::kill(pid, 0) == 0);
109 }
110 }
111 }
112
113 return false;
114 }
115
116
117 bool kill_file(const std::string &filename)
118 {
119 if (filename.empty())
120 {
121 return true;
122 }
123
124 FILE *fp;
125 if ((fp= fopen(filename.c_str(), "r")))
126 {
127 char pid_buffer[1024];
128
129 char *ptr= fgets(pid_buffer, sizeof(pid_buffer), fp);
130 fclose(fp);
131
132 if (ptr)
133 {
134 pid_t pid= (pid_t)atoi(pid_buffer);
135 if (pid != 0)
136 {
137 bool ret= kill_pid(pid);
138 unlink(filename.c_str()); // If this happens we may be dealing with a dead server that left its pid file.
139
140 return ret;
141 }
142 }
143 }
144
145 return false;
146 }
147
148 #define STRINGIFY(x) #x
149 #define TOSTRING(x) STRINGIFY(x)
150 #define LIBTEST_AT __FILE__ ":" TOSTRING(__LINE__)
151
152 pid_t get_pid_from_file(const std::string &filename, std::stringstream& error_message)
153 {
154 pid_t ret= -1;
155 FILE *fp;
156
157 if (filename.empty())
158 {
159 error_message << LIBTEST_AT << " empty pid file";
160 return ret;
161 }
162
163 if ((fp= fopen(filename.c_str(), "r")))
164 {
165 char pid_buffer[1024];
166
167 char *ptr= fgets(pid_buffer, sizeof(pid_buffer), fp);
168 fclose(fp);
169
170 if (ptr)
171 {
172 ret= (pid_t)atoi(pid_buffer);
173 if (ret < 1)
174 {
175 error_message << LIBTEST_AT << " Invalid pid was read from file " << filename;
176 }
177 }
178 else
179 {
180 error_message << LIBTEST_AT << " File " << filename << " was empty ";
181 }
182
183 return ret;
184 }
185 else
186 {
187 char buffer[1024];
188 char *current_directory= getcwd(buffer, sizeof(buffer));
189 error_message << "Error while opening " << current_directory << "/" << filename << " " << strerror(errno);
190 }
191
192 return ret;
193 }