Changeset: cdb85d8e63ad for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=cdb85d8e63ad
Modified Files:
        tools/merovingian/daemon/forkmserver.c
Branch: default
Log Message:

[monetdbd] Make profilerstart command more robust

If the server or stethoscope crashed before, the pid file is still
there, so the next time we try to start stethoscope, it will fail.

Now the profilerstart command will check if a stethoscope process with
the recorded pid is running. If not, we start stethoscope, assuming
that something went wrong before.


diffs (115 lines):

diff --git a/tools/merovingian/daemon/forkmserver.c 
b/tools/merovingian/daemon/forkmserver.c
--- a/tools/merovingian/daemon/forkmserver.c
+++ b/tools/merovingian/daemon/forkmserver.c
@@ -755,6 +755,8 @@ forkMserver(char *database, sabdb** stat
        return(newErr("%s", strerror(errno)));
 }
 
+#define BUFLEN 1024
+
 /**
  * Fork stethoscope and detatch, after performing sanity checks. The assumption
  * is that each mserver5 process can have at most one stethoscope process
@@ -882,18 +884,94 @@ fork_profiler(char *dbname, sabdb **stat
        }
        snprintf(pidfilename, pidfnlen, "%s/profiler.pid", *log_path);
 
-       /* Make sure that the pid file is does not exist */
+       /* Make sure another instance of stethoscope is not running. */
        error_code = stat(pidfilename, &path_info);
        if (error_code != -1) {
-               error = newErr("pid file %s already exists. Is the profiler 
already running?",
-                                          pidfilename);
-               free(*log_path);
-               *log_path = NULL;
-               goto cleanup;
+               char buf[8];
+               long pid;
+               /* The pid file exists. See if a process with this pid exists,
+                * and if yes, if it is stethoscope.
+                */
+
+               /* We cannot open the pidfile, bail out */
+               if ((pidfile = fopen(pidfilename, "r")) == NULL) {
+                       error = newErr("pid file %s already exists, but is not 
accessible. Is the profiler already running?",
+                                                  pidfilename);
+                       free(*log_path);
+                       *log_path = NULL;
+                       goto cleanup;
+               }
+
+               if (fgets(buf, sizeof(buf), pidfile) == NULL) {
+                       fclose(pidfile);
+                       error = newErr("cannot read from pid file %s: %s\n",
+                                                  pidfilename, 
strerror(errno));
+                       free(*log_path);
+                       *log_path = NULL;
+                       goto cleanup;
+               }
+               fclose(pidfile);
+
+               /* Verify that what we read is actually a number */
+               errno = 0;
+               pid = strtol(buf, NULL, 10);
+               if (errno != 0) {
+                       error = newErr("contents of the pid file are not 
correct: %s\n",
+                                                  strerror(errno));
+                       free(*log_path);
+                       *log_path = NULL;
+                       goto cleanup;
+               }
+
+               // Open /proc/<pid>/comm and compare the contents to 
"stethoscope"
+               // This of course is specific to Linux
+               size_t fn_size = strlen("/proc/comm") + 9;
+               char *filename = malloc(fn_size);
+               if (filename == NULL) {
+                       error = newErr("cannot allocate %zu bytes: %s\n",
+                                                  fn_size, strerror(errno));
+                       free(*log_path);
+                       *log_path = NULL;
+                       goto cleanup;
+               }
+               snprintf(filename, fn_size, "/proc/%ld/comm", pid);
+
+               FILE *comm = fopen(filename, "r");
+               if (comm == NULL) {
+                       /* We cannot open the file for the process with the 
specified pid,
+                        * so the process is not running.
+                        */
+                       free(filename);
+                       goto startup;
+               }
+               char buf2[BUFLEN];
+               fread(buf2, 1, BUFLEN, comm);
+
+               if(ferror(comm)) {
+                       error = newErr("cannot read from file %s\n", filename);
+                       free(filename);
+                       free(*log_path);
+                       fclose(comm);
+                       *log_path = NULL;
+                       goto cleanup;
+               }
+
+               char expected_command[] = "stethoscope";
+               size_t command_len = strlen(expected_command);
+               if (strncmp(buf2, expected_command, command_len) == 0) {
+                       error = newErr("profiler already running for %s\n", 
dbname);
+                       free(filename);
+                       free(*log_path);
+                       fclose(comm);
+                       *log_path = NULL;
+                       goto cleanup;
+               }
+
+               fclose(comm);
+               free(filename);
        }
 
-       /* TODO: if the pid file exists read it and check if stethoscope with 
the
-        * given pid is running */
+  startup:
        /* Open the pid file */
        if ((pidfile = fopen(pidfilename, "w")) == NULL) {
                error = newErr("unable to open %s for writing", pidfilename);
_______________________________________________
checkin-list mailing list
checkin-list@monetdb.org
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to