runtests
[awesomized/libmemcached] / test / lib / Server.cpp
index 17bafe74ca8a9c96441a21456010899635cfbf81..dddb68d9f733ceecf98da9ae9f3e5bca83bce323 100644 (file)
@@ -1,5 +1,5 @@
 #include "Server.hpp"
-#include "Connection.hpp"
+#include "Retry.hpp"
 #include "ForkAndExec.hpp"
 
 #include <sys/wait.h>
@@ -39,11 +39,16 @@ static inline void pushArg(vector<char *> &arr, const string &arg) {
 
 optional<string> Server::handleArg(vector<char *> &arr, const string &arg, const arg_func_t &next_arg) {
   pushArg(arr, arg);
-  if (arg == "-p" || arg == "--port") {
+  if (arg == "-U" || arg == "--udp-port") {
+    auto port = next_arg(arg);
+    pushArg(arr, port);
+    pushArg(arr, "-p");
+    pushArg(arr, port);
+    socket_or_port = stoi(port);
+    return port;
+  } else if (arg == "-p" || arg == "--port") {
     auto port = next_arg(arg);
     pushArg(arr, port);
-//    pushArg(arr, "-U");
-//    pushArg(arr, port);
     socket_or_port = stoi(port);
     return port;
   } else if (arg == "-s" || arg == "--unix-socket") {
@@ -62,7 +67,8 @@ vector<char *> Server::createArgv()  {
   vector<char *> arr;
 
   pushArg(arr, binary);
-  //pushArg(arr, "-v");
+  pushArg(arr, "-u");
+  pushArg(arr, "nobody");
 
   for (auto it = args.cbegin(); it != args.cend(); ++it) {
     if (holds_alternative<arg_t>(*it)) {
@@ -111,7 +117,7 @@ optional<Server::ChildProc> Server::start() {
   return ChildProc{pid, pipe};
 }
 
-bool Server::isListening() {
+bool Server::isListening() const {
   MemcachedPtr memc;
 
   if (holds_alternative<string>(socket_or_port)) {
@@ -130,13 +136,36 @@ bool Server::isListening() {
   }
 
   Malloced stat(memcached_stat(*memc, nullptr, nullptr));
-  if (!*stat || !stat->pid || stat->pid != pid) {
+  if (!*stat || !stat->pid || stat->pid == -1) {
+    return false;
+  }
+  if (stat->pid != pid) {
+    cerr << "Another server is listening on " << socket_or_port
+         << " (expected pid " << pid << " found pid " << stat->pid << ")\n";
     return false;
   }
 
   return true;
 }
 
+bool Server::ensureListening() {
+  if (!start()) {
+    return false;
+  }
+  return Retry{[this] {
+    again:
+    start();
+    if (!isListening()) {
+      auto old = pid;
+      if (tryWait()) {
+        cerr << "Collected zombie " << *this << "(old pid=" << old << ")\n";
+        goto again;
+      }
+    }
+    return isListening();
+  }}();
+}
+
 bool Server::stop() {
   if (!pid) {
     return true;
@@ -162,8 +191,20 @@ bool Server::check() {
 
 bool Server::wait(int flags) {
   if (pid && pid == waitpid(pid, &status, flags)) {
-    if (drain().length()) {
-      cerr << "Ouput of " << *this << ":\n" << output << endl;
+    if (drain().length() &&
+        output.rfind("Signal handled: Terminated", 0) != 0) {
+      cerr << "Output of " << *this << ":\n";
+
+      istringstream iss{output};
+      string line;
+
+      while (getline(iss, line)) {
+        cerr << "  " << line << "\n";
+      }
+
+      if (output.back() != '\n') {
+        cerr << endl;
+      }
       output.clear();
     }
     pid = 0;