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