server.cc 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  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. #include <libtest/common.h>
  22. #include <cassert>
  23. #include <cerrno>
  24. #include <cstdlib>
  25. #include <iostream>
  26. #include <algorithm>
  27. #include <functional>
  28. #include <locale>
  29. // trim from end
  30. static inline std::string &rtrim(std::string &s)
  31. {
  32. s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
  33. return s;
  34. }
  35. #include <libtest/server.h>
  36. #include <libtest/stream.h>
  37. #include <libtest/killpid.h>
  38. extern "C" {
  39. static bool exited_successfully(int status, const std::string &command)
  40. {
  41. if (status == 0)
  42. {
  43. return true;
  44. }
  45. if (WIFEXITED(status) == true)
  46. {
  47. int ret= WEXITSTATUS(status);
  48. if (ret == 0)
  49. {
  50. return true;
  51. }
  52. else if (ret == EXIT_FAILURE)
  53. {
  54. libtest::Error << "Command executed, but returned EXIT_FAILURE: " << command;
  55. }
  56. else
  57. {
  58. libtest::Error << "Command executed, but returned " << ret;
  59. }
  60. }
  61. else if (WIFSIGNALED(status) == true)
  62. {
  63. int ret_signal= WTERMSIG(status);
  64. libtest::Error << "Died from signal " << strsignal(ret_signal);
  65. }
  66. return false;
  67. }
  68. }
  69. namespace libtest {
  70. std::ostream& operator<<(std::ostream& output, const Server &arg)
  71. {
  72. if (arg.is_socket())
  73. {
  74. output << arg.hostname();
  75. }
  76. else
  77. {
  78. output << arg.hostname() << ":" << arg.port();
  79. }
  80. if (arg.has_pid())
  81. {
  82. output << " Pid:" << arg.pid();
  83. }
  84. if (arg.has_socket())
  85. {
  86. output << " Socket:" << arg.socket();
  87. }
  88. if (not arg.running().empty())
  89. {
  90. output << " Exec:" << arg.running();
  91. }
  92. return output; // for multiple << operators
  93. }
  94. Server::Server(const std::string& host_arg, const in_port_t port_arg, bool is_socket_arg) :
  95. _is_socket(is_socket_arg),
  96. _pid(-1),
  97. _port(port_arg),
  98. _hostname(host_arg)
  99. {
  100. }
  101. Server::~Server()
  102. {
  103. if (has_pid() and not kill(_pid))
  104. {
  105. Error << "Unable to kill:" << *this;
  106. }
  107. }
  108. // If the server exists, kill it
  109. bool Server::cycle()
  110. {
  111. uint32_t limit= 3;
  112. // Try to ping, and kill the server #limit number of times
  113. pid_t current_pid;
  114. while (--limit and is_pid_valid(current_pid= get_pid()))
  115. {
  116. if (kill(current_pid))
  117. {
  118. Log << "Killed existing server," << *this << " with pid:" << current_pid;
  119. dream(0, 50000);
  120. continue;
  121. }
  122. }
  123. // For whatever reason we could not kill it, and we reached limit
  124. if (limit == 0)
  125. {
  126. Error << "Reached limit, could not kill server pid:" << current_pid;
  127. return false;
  128. }
  129. return true;
  130. }
  131. // Grab a one off command
  132. bool Server::command(std::string& command_arg)
  133. {
  134. rebuild_base_command();
  135. command_arg+= _base_command;
  136. if (args(command_arg))
  137. {
  138. return true;
  139. }
  140. return false;
  141. }
  142. bool Server::wait_for_pidfile() const
  143. {
  144. Wait wait(pid_file(), 4);
  145. return wait.successful();
  146. }
  147. bool Server::start()
  148. {
  149. // If we find that we already have a pid then kill it.
  150. if (has_pid() and not kill(_pid))
  151. {
  152. Error << "Could not kill() existing server during start() pid:" << _pid;
  153. return false;
  154. }
  155. assert(not has_pid());
  156. _running.clear();
  157. if (not command(_running))
  158. {
  159. Error << "Could not build command()";
  160. return false;
  161. }
  162. if (is_valgrind() or is_helgrind())
  163. {
  164. _running+= " &";
  165. }
  166. int ret= system(_running.c_str());
  167. if (not exited_successfully(ret, _running))
  168. {
  169. Error << "system() failed:" << strerror(errno);
  170. _running.clear();
  171. return false;
  172. }
  173. if (is_helgrind() or is_valgrind())
  174. {
  175. dream(5, 50000);
  176. }
  177. if (pid_file_option() and not pid_file().empty())
  178. {
  179. Wait wait(pid_file(), 8);
  180. if (not wait.successful())
  181. {
  182. Error << "Unable to open pidfile for: " << _running;
  183. }
  184. }
  185. int count= is_helgrind() or is_valgrind() ? 20 : 5;
  186. while (not ping() and --count)
  187. {
  188. dream(0, 50000);
  189. }
  190. if (count == 0)
  191. {
  192. // If we happen to have a pid file, lets try to kill it
  193. if (pid_file_option() and not pid_file().empty())
  194. {
  195. kill_file(pid_file());
  196. }
  197. Error << "Failed to ping() server started with:" << _running;
  198. _running.clear();
  199. return false;
  200. }
  201. // A failing get_pid() at this point is considered an error
  202. _pid= get_pid(true);
  203. return has_pid();
  204. }
  205. void Server::reset_pid()
  206. {
  207. _running.clear();
  208. _pid_file.clear();
  209. _pid= -1;
  210. }
  211. pid_t Server::pid()
  212. {
  213. return _pid;
  214. }
  215. bool Server::set_socket_file()
  216. {
  217. char file_buffer[FILENAME_MAX];
  218. file_buffer[0]= 0;
  219. if (broken_pid_file())
  220. {
  221. snprintf(file_buffer, sizeof(file_buffer), "/tmp/%s.socketXXXXXX", name());
  222. }
  223. else
  224. {
  225. snprintf(file_buffer, sizeof(file_buffer), "var/run/%s.socketXXXXXX", name());
  226. }
  227. int fd;
  228. if ((fd= mkstemp(file_buffer)) == -1)
  229. {
  230. perror(file_buffer);
  231. return false;
  232. }
  233. close(fd);
  234. unlink(file_buffer);
  235. _socket= file_buffer;
  236. return true;
  237. }
  238. bool Server::set_pid_file()
  239. {
  240. char file_buffer[FILENAME_MAX];
  241. file_buffer[0]= 0;
  242. if (broken_pid_file())
  243. {
  244. snprintf(file_buffer, sizeof(file_buffer), "/tmp/%s.pidXXXXXX", name());
  245. }
  246. else
  247. {
  248. snprintf(file_buffer, sizeof(file_buffer), "var/run/%s.pidXXXXXX", name());
  249. }
  250. int fd;
  251. if ((fd= mkstemp(file_buffer)) == -1)
  252. {
  253. perror(file_buffer);
  254. return false;
  255. }
  256. close(fd);
  257. unlink(file_buffer);
  258. _pid_file= file_buffer;
  259. return true;
  260. }
  261. bool Server::set_log_file()
  262. {
  263. char file_buffer[FILENAME_MAX];
  264. file_buffer[0]= 0;
  265. snprintf(file_buffer, sizeof(file_buffer), "var/log/%s.logXXXXXX", name());
  266. int fd;
  267. if ((fd= mkstemp(file_buffer)) == -1)
  268. {
  269. perror(file_buffer);
  270. return false;
  271. }
  272. close(fd);
  273. _log_file= file_buffer;
  274. return true;
  275. }
  276. void Server::rebuild_base_command()
  277. {
  278. _base_command.clear();
  279. if (is_libtool())
  280. {
  281. _base_command+= libtool();
  282. }
  283. if (is_debug() and getenv("GDB_COMMAND"))
  284. {
  285. _base_command+= getenv("GDB_COMMAND");
  286. _base_command+= " ";
  287. }
  288. else if (is_valgrind() and getenv("VALGRIND_COMMAND"))
  289. {
  290. _base_command+= getenv("VALGRIND_COMMAND");
  291. _base_command+= " ";
  292. }
  293. else if (is_helgrind() and getenv("HELGRIND_COMMAND"))
  294. {
  295. _base_command+= getenv("HELGRIND_COMMAND");
  296. _base_command+= " ";
  297. }
  298. if (is_libtool())
  299. {
  300. if (getenv("PWD"))
  301. {
  302. _base_command+= getenv("PWD");
  303. _base_command+= "/";
  304. }
  305. }
  306. _base_command+= executable();
  307. }
  308. void Server::set_extra_args(const std::string &arg)
  309. {
  310. _extra_args= arg;
  311. }
  312. bool Server::args(std::string& options)
  313. {
  314. std::stringstream arg_buffer;
  315. // Set a log file if it was requested (and we can)
  316. if (getenv("LIBTEST_LOG") and log_file_option())
  317. {
  318. if (not set_log_file())
  319. {
  320. return false;
  321. }
  322. arg_buffer << " " << log_file_option() << _log_file;
  323. }
  324. // Update pid_file
  325. if (pid_file_option())
  326. {
  327. if (_pid_file.empty() and not set_pid_file())
  328. {
  329. return false;
  330. }
  331. arg_buffer << " " << pid_file_option() << pid_file();
  332. }
  333. assert(daemon_file_option());
  334. if (daemon_file_option() and not is_valgrind() and not is_helgrind())
  335. {
  336. arg_buffer << " " << daemon_file_option();
  337. }
  338. if (_is_socket and socket_file_option())
  339. {
  340. if (not set_socket_file())
  341. {
  342. return false;
  343. }
  344. arg_buffer << " " << socket_file_option() << "\"" << _socket << "\"";
  345. }
  346. assert(port_option());
  347. if (port_option() and _port > 0)
  348. {
  349. arg_buffer << " " << port_option() << _port;
  350. }
  351. options+= arg_buffer.str();
  352. if (not _extra_args.empty())
  353. {
  354. options+= _extra_args;
  355. }
  356. return true;
  357. }
  358. bool Server::is_debug() const
  359. {
  360. return bool(getenv("LIBTEST_MANUAL_GDB"));
  361. }
  362. bool Server::is_valgrind() const
  363. {
  364. return bool(getenv("LIBTEST_MANUAL_VALGRIND"));
  365. }
  366. bool Server::is_helgrind() const
  367. {
  368. return bool(getenv("LIBTEST_MANUAL_HELGRIND"));
  369. }
  370. bool Server::kill(pid_t pid_arg)
  371. {
  372. if (check_pid(pid_arg) and kill_pid(pid_arg)) // If we kill it, reset
  373. {
  374. if (broken_pid_file() and not pid_file().empty())
  375. {
  376. unlink(pid_file().c_str());
  377. }
  378. if (broken_socket_cleanup() and has_socket() and not socket().empty())
  379. {
  380. unlink(socket().c_str());
  381. }
  382. reset_pid();
  383. return true;
  384. }
  385. return false;
  386. }
  387. } // namespace libtest