Remove openbsd warnings.
[m6w6/libmemcached] / tests / server.c
index c0521e5bb26d5dabc1d615d82048b2c8fb8bd1ec..84f15de09df4192eaef8641c5b3297e84bb8fdc7 100644 (file)
 
 #define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10
 
+#define PID_FILE_BASE "/tmp/%ulibmemcached_memc.pid"
+
 #include "config.h"
 
+#include <assert.h>
+#include <limits.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <sys/time.h>
 #include <time.h>
-#include <assert.h>
-#include <signal.h>
+#include <unistd.h>
+
 #include <libmemcached/memcached.h>
 #include <libmemcached/util.h>
-#include <unistd.h>
-#include <time.h>
 
 #include "server.h"
 
+static struct timespec global_sleep_value= { .tv_sec= 0, .tv_nsec= 50000 };
+
+static void global_sleep(void)
+{
+#ifdef WIN32
+  sleep(1);
+#else
+  nanosleep(&global_sleep_value, NULL);
+#endif
+}
+
+static void kill_file(const char *file_buffer)
+{
+  FILE *fp= fopen(file_buffer, "r");
+
+  while ((fp= fopen(file_buffer, "r")))
+  {
+    char pid_buffer[1024];
+
+    if (fgets(pid_buffer, sizeof(pid_buffer), fp) != NULL)
+    {
+      pid_t pid= (pid_t)atoi(pid_buffer);
+      if (pid != 0)
+      {
+        if (kill(pid, SIGTERM) == -1)
+        {
+          remove(file_buffer); // If this happens we may be dealing with a dead server that left its pid file.
+        }
+        else
+        {
+          uint32_t counter= 3;
+          while ((kill(pid, 0) == 0) && --counter)
+          {
+            global_sleep();
+          }
+        }
+      }
+    }
+
+    global_sleep();
+
+    fclose(fp);
+  }
+}
+
 void server_startup(server_startup_st *construct)
 {
   if ((construct->server_list= getenv("MEMCACHED_SERVERS")))
@@ -48,85 +97,118 @@ void server_startup(server_startup_st *construct)
 
       for (uint32_t x= 0; x < construct->count; x++)
       {
-        char buffer[1024]; /* Nothing special for number */
-        int count;
         int status;
+        in_port_t port;
 
-        sprintf(buffer, "/tmp/%umemc.pid", x);
-        if (access(buffer, F_OK) == 0)
         {
-          FILE *fp= fopen(buffer, "r");
-          remove(buffer);
+          char *var;
+          char variable_buffer[1024];
 
-          if (fp != NULL)
-          {
-            if (fgets(buffer, sizeof(buffer), fp) != NULL)
-            {
-              pid_t pid= (pid_t)atoi(buffer);
-              if (pid != 0)
-                kill(pid, SIGTERM);
-            }
+          snprintf(variable_buffer, sizeof(variable_buffer), "LIBMEMCACHED_PORT_%u", x);
 
-            fclose(fp);
+          if ((var= getenv(variable_buffer)))
+          {
+            port= (in_port_t)atoi(var);
+          }
+          else
+          {
+            port= (in_port_t)(x + TEST_PORT_BASE);
           }
         }
 
+        char buffer[PATH_MAX];
+        snprintf(buffer, sizeof(buffer), PID_FILE_BASE, x);
+        kill_file(buffer);
+
         if (x == 0)
         {
-          sprintf(buffer, "%s -d -P /tmp/%umemc.pid -t 1 -p %u -U %u -m 128",
-                 MEMCACHED_BINARY, x, x + TEST_PORT_BASE, x + TEST_PORT_BASE);
+          snprintf(buffer, sizeof(buffer), "%s -d -u root -P "PID_FILE_BASE" -t 1 -p %u -U %u -m 128",
+                   MEMCACHED_BINARY, x, port, port);
         }
         else
         {
-          sprintf(buffer, "%s -d -P /tmp/%umemc.pid -t 1 -p %u -U %u",
-                 MEMCACHED_BINARY, x, x + TEST_PORT_BASE, x + TEST_PORT_BASE);
+          snprintf(buffer, sizeof(buffer), "%s -d -u root -P "PID_FILE_BASE" -t 1 -p %u -U %u",
+                   MEMCACHED_BINARY, x, port, port);
         }
-       if (libmemcached_util_ping("localhost", (in_port_t)(x + TEST_PORT_BASE), NULL))
+       if (libmemcached_util_ping("localhost", port, NULL))
        {
-         fprintf(stderr, "Server on port %u already exists\n", x + TEST_PORT_BASE);
+         fprintf(stderr, "Server on port %u already exists\n", port);
        }
        else
        {
          status= system(buffer);
          fprintf(stderr, "STARTING SERVER: %s  status:%d\n", buffer, status);
        }
-        count= sprintf(end_ptr, "localhost:%u,", x + TEST_PORT_BASE);
+        int count;
+        size_t remaining_length= sizeof(server_string_buffer) - (size_t)(end_ptr -server_string_buffer);
+        count= snprintf(end_ptr, remaining_length,  "localhost:%u,", port);
+
+        if ((size_t)count >= remaining_length || count < 0)
+        {
+          fprintf(stderr, "server names grew to be larger then buffer allowed\n");
+          abort();
+        }
         end_ptr+= count;
       }
       *end_ptr= 0;
 
+
+      int *pids= calloc(construct->count, sizeof(int));
       for (uint32_t x= 0; x < construct->count; x++)
       {
-        uint32_t counter= 3;
-        char buffer[1024]; /* Nothing special for number */
+        char buffer[PATH_MAX]; /* Nothing special for number */
 
-        snprintf(buffer, sizeof(buffer), "/tmp/%umemc.pid", x);
+        snprintf(buffer, sizeof(buffer), PID_FILE_BASE, x);
 
-        while (--counter)
+        uint32_t counter= 3000; // Absurd, just to catch run away process
+        while (pids[x] <= 0  && --counter)
         {
-          int memcached_pid;
-
-          FILE *file;
-          file= fopen(buffer, "r");
-          if (file == NULL)
+          FILE *file= fopen(buffer, "r");
+          if (file)
           {
-            struct timespec req= { .tv_sec= 0, .tv_nsec= 5000 };
-            nanosleep(&req, NULL);
+            char pid_buffer[1024];
+            char *found= fgets(pid_buffer, sizeof(pid_buffer), file);
+
+            if (found)
+            {
+              pids[x]= atoi(pid_buffer);
+              fclose(file);
 
-            continue;
+              if (pids[x] > 0)
+                break;
+            }
+            fclose(file);
           }
-          char *found= fgets(buffer, sizeof(buffer), file);
-          if (!found)
+          global_sleep();
+        }
+
+        bool was_started= false;
+        if (pids[x] > 0)
+        {
+          counter= 30;
+          while (--counter)
           {
-            abort();
+            if (kill(pids[x], 0) == 0)
+            {
+              was_started= true;
+              break;
+            }
+            global_sleep();
           }
-          // Yes, we currently pitch this and don't make use of it.
-          memcached_pid= atoi(buffer);
-          fclose(file);
         }
 
-
+        if (was_started == false)
+        {
+          fprintf(stderr, "Failed to open buffer %s(%d)\n", buffer, pids[x]);
+          for (uint32_t y= 0; y < construct->count; y++)
+          {
+            if (pids[y] > 0)
+              kill(pids[y], SIGTERM);
+          }
+          abort();
+        }
       }
+      free(pids);
 
       construct->server_list= strdup(server_string_buffer);
     }
@@ -154,13 +236,9 @@ void server_shutdown(server_startup_st *construct)
   {
     for (uint32_t x= 0; x < construct->count; x++)
     {
-      char buffer[1024]; /* Nothing special for number */
-      sprintf(buffer, "cat /tmp/%umemc.pid | xargs kill", x);
-      /* We have to check the return value of this or the compiler will yell */
-      int sys_ret= system(buffer);
-      assert(sys_ret != -1);
-      sprintf(buffer, "/tmp/%umemc.pid", x);
-      unlink(buffer);
+      char file_buffer[PATH_MAX]; /* Nothing special for number */
+      snprintf(file_buffer, sizeof(file_buffer), PID_FILE_BASE, x);
+      kill_file(file_buffer);
     }
 
     free(construct->server_list);