Changeset: 805d8e0173c8 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=805d8e0173c8
Modified Files:
tools/merovingian/daemon/forkmserver.c
Branch: Jul2017
Log Message:
Fix potential race condition. This may very well fix bug 6452.
Lock the _mero_topdp_lock lock *before* forking, so that when the
newly started process dies quickly, it's not harvested before we enter
it in our administration. In this way harvesting does something.
Also, try to do as little as possible between fork and exec in the
child process.
diffs (truncated from 648 to 300 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
@@ -199,6 +199,24 @@ forkMserver(char *database, sabdb** stat
char upmax[8];
confkeyval *ckv, *kv, *list;
SABdbState state;
+ char *sabdbfarm;
+ char dbpath[1024];
+ char dbextra_path[1024];
+ char port[24];
+ char muri[512]; /* possibly undersized */
+ char usock[512];
+ char mydoproxy;
+ char nthreads[24];
+ char nclients[24];
+ char pipeline[512];
+ char *readonly = NULL;
+ char *embeddedr = NULL;
+ char *embeddedpy = NULL;
+ char *dbextra = NULL;
+ char *argv[512]; /* for the exec arguments */
+ char property_other[1024];
+ int c = 0;
+ unsigned int mport;
er = msab_getStatus(stats, database);
if (er != NULL) {
@@ -402,90 +420,158 @@ forkMserver(char *database, sabdb** stat
database, database));
}
+ er = msab_getDBfarm(&sabdbfarm);
+ if (er != NULL) {
+ err e = newErr("%s", er);
+ free(er);
+ return(e);
+ }
+
+ mydoproxy = strcmp(getConfVal(_mero_props, "forward"), "proxy") == 0;
+
+ kv = findConfKey(ckv, "nthreads");
+ if (kv->val == NULL)
+ kv = findConfKey(_mero_db_props, "nthreads");
+ if (kv->val != NULL) {
+ snprintf(nthreads, sizeof(nthreads), "gdk_nr_threads=%s",
kv->val);
+ } else {
+ nthreads[0] = '\0';
+ }
+
+ kv = findConfKey(ckv, "nclients");
+ if (kv->val == NULL)
+ kv = findConfKey(_mero_db_props, "nclients");
+ if (kv->val != NULL) {
+ snprintf(nclients, sizeof(nclients), "max_clients=%s", kv->val);
+ } else {
+ nclients[0] = '\0';
+ }
+
+ kv = findConfKey(ckv, "optpipe");
+ if (kv->val == NULL)
+ kv = findConfKey(_mero_db_props, "optpipe");
+ if (kv->val != NULL) {
+ snprintf(pipeline, sizeof(pipeline), "sql_optimizer=%s",
kv->val);
+ } else {
+ pipeline[0] = '\0';
+ }
+
+ kv = findConfKey(ckv, "readonly");
+ if (kv->val != NULL && strcmp(kv->val, "no") != 0)
+ readonly = "--readonly";
+
+ kv = findConfKey(ckv, "embedr");
+ if (kv->val != NULL && strcmp(kv->val, "no") != 0)
+ embeddedr = "embedded_r=true";
+
+ kv = findConfKey(ckv, "embedpy");
+ if (kv->val != NULL && strcmp(kv->val, "no") != 0)
+ embeddedpy = "embedded_py=true";
+
+ kv = findConfKey(ckv, "embedpy3");
+ if (kv->val != NULL && strcmp(kv->val, "no") != 0) {
+ if (embeddedpy) {
+ // only one python version can be active at a time
+ return newErr("attempting to start mserver with both
embedded python2 and embedded python3; only one python version can be active at
a time\n");
+ }
+ embeddedpy = "embedded_py=3";
+ }
+ kv = findConfKey(ckv, "dbextra");
+ if (kv != NULL && kv->val != NULL) {
+ dbextra = kv->val;
+ }
+
+
+ mport = (unsigned int)getConfNum(_mero_props, "port");
+
+ /* ok, now exec that mserver we want */
+ snprintf(dbpath, sizeof(dbpath),
+ "--dbpath=%s/%s", sabdbfarm, database);
+ snprintf(vaultkey, sizeof(vaultkey),
+ "monet_vault_key=%s/.vaultkey", (*stats)->path);
+ snprintf(muri, sizeof(muri),
+ "merovingian_uri=mapi:monetdb://%s:%u/%s",
+ _mero_hostname, mport, database);
+ argv[c++] = _mero_mserver;
+ argv[c++] = dbpath;
+ argv[c++] = "--set"; argv[c++] = muri;
+ if (dbextra != NULL) {
+ snprintf(dbextra_path, sizeof(dbextra_path),
+ "--dbextra=%s", dbextra);
+ argv[c++] = dbextra_path;
+ }
+ if (mydoproxy == 1) {
+ struct sockaddr_un s; /* only for sizeof(s.sun_path) :( */
+ argv[c++] = "--set"; argv[c++] = "mapi_open=false";
+ /* we "proxy", so we can just solely use UNIX domain sockets
+ * internally. Before we hit our head, check if we can
+ * actually use a UNIX socket (due to pathlength) */
+ if (strlen((*stats)->path) + 11 < sizeof(s.sun_path)) {
+ snprintf(port, sizeof(port), "mapi_port=0");
+ snprintf(usock, sizeof(usock),
"mapi_usock=%s/.mapi.sock",
+ (*stats)->path);
+ } else {
+ argv[c++] = "--set"; argv[c++] = "mapi_autosense=true";
+ /* for logic here, see comment below */
+ snprintf(port, sizeof(port), "mapi_port=%u", mport + 1);
+ snprintf(usock, sizeof(usock), "mapi_usock=");
+ }
+ } else {
+ argv[c++] = "--set"; argv[c++] = "mapi_open=true";
+ argv[c++] = "--set"; argv[c++] = "mapi_autosense=true";
+ /* avoid this mserver binding to the same port as merovingian
+ * but on another interface, (INADDR_ANY ... sigh) causing
+ * endless redirects since 0.0.0.0 is not a valid address to
+ * connect to, and hence the hostname is advertised instead */
+ snprintf(port, sizeof(port), "mapi_port=%u", mport + 1);
+ snprintf(usock, sizeof(usock), "mapi_usock=");
+ }
+ argv[c++] = "--set"; argv[c++] = port;
+ argv[c++] = "--set"; argv[c++] = usock;
+ argv[c++] = "--set"; argv[c++] = vaultkey;
+ if (nthreads[0] != '\0') {
+ argv[c++] = "--set"; argv[c++] = nthreads;
+ }
+ if (nclients[0] != '\0') {
+ argv[c++] = "--set"; argv[c++] = nclients;
+ }
+ if (pipeline[0] != '\0') {
+ argv[c++] = "--set"; argv[c++] = pipeline;
+ }
+ if (embeddedr != NULL) {
+ argv[c++] = "--set"; argv[c++] = embeddedr;
+ }
+ if (embeddedpy != NULL) {
+ argv[c++] = "--set"; argv[c++] = embeddedpy;
+ }
+ if (readonly != NULL) {
+ argv[c++] = readonly;
+ }
+ /* get the rest (non-default) mserver props set in the conf file */
+ list = ckv;
+ while (list->key != NULL) {
+ if (list->val != NULL && !defaultProperty(list->key)) {
+ argv[c++] = "--set";
+ snprintf(property_other, sizeof(property_other),
"%s=%s", list->key, list->val);
+ argv[c++] = strdup(property_other);
+ }
+ list++;
+ }
+
+ /* keep this one last for easy copy/paste with gdb */
+ argv[c++] = "--set"; argv[c++] = "monet_daemon=yes";
+
+ argv[c++] = NULL;
+
+ freeConfFile(ckv);
+ free(ckv); /* can make ckv static and reuse it all the time */
+
+ /* make sure no entries are shot while adding and that we
+ * deliver a consistent state */
+ pthread_mutex_lock(&_mero_topdp_lock);
+
pid = fork();
if (pid == 0) {
- char *sabdbfarm;
- char dbpath[1024];
- char dbextra_path[1024];
- char port[24];
- char muri[512]; /* possibly undersized */
- char usock[512];
- char mydoproxy;
- char nthreads[24];
- char nclients[24];
- char pipeline[512];
- char *readonly = NULL;
- char *embeddedr = NULL;
- char *embeddedpy = NULL;
- char *dbextra = NULL;
- char *argv[512]; /* for the exec arguments */
- char property_other[1024];
- int c = 0;
- unsigned int mport;
-
- er = msab_getDBfarm(&sabdbfarm);
- if (er != NULL) {
- Mfprintf(stderr, "unexpected error: %s\n", er);
- exit(1);
- }
-
- mydoproxy = strcmp(getConfVal(_mero_props, "forward"), "proxy")
== 0;
-
- kv = findConfKey(ckv, "nthreads");
- if (kv->val == NULL)
- kv = findConfKey(_mero_db_props, "nthreads");
- if (kv->val != NULL) {
- snprintf(nthreads, sizeof(nthreads),
"gdk_nr_threads=%s", kv->val);
- } else {
- nthreads[0] = '\0';
- }
-
- kv = findConfKey(ckv, "nclients");
- if (kv->val == NULL)
- kv = findConfKey(_mero_db_props, "nclients");
- if (kv->val != NULL) {
- snprintf(nclients, sizeof(nclients), "max_clients=%s",
kv->val);
- } else {
- nclients[0] = '\0';
- }
-
- kv = findConfKey(ckv, "optpipe");
- if (kv->val == NULL)
- kv = findConfKey(_mero_db_props, "optpipe");
- if (kv->val != NULL) {
- snprintf(pipeline, sizeof(pipeline),
"sql_optimizer=%s", kv->val);
- } else {
- pipeline[0] = '\0';
- }
-
- kv = findConfKey(ckv, "readonly");
- if (kv->val != NULL && strcmp(kv->val, "no") != 0)
- readonly = "--readonly";
-
- kv = findConfKey(ckv, "embedr");
- if (kv->val != NULL && strcmp(kv->val, "no") != 0)
- embeddedr = "embedded_r=true";
-
- kv = findConfKey(ckv, "embedpy");
- if (kv->val != NULL && strcmp(kv->val, "no") != 0)
- embeddedpy = "embedded_py=true";
-
- kv = findConfKey(ckv, "embedpy3");
- if (kv->val != NULL && strcmp(kv->val, "no") != 0) {
- if (embeddedpy) {
- // only one python version can be active at a
time
- Mfprintf(stderr, "attempting to start mserver
with both embedded python2 and embedded python3; only one python version can be
active at a time\n");
- exit(1);
- }
- embeddedpy = "embedded_py=3";
- }
- kv = findConfKey(ckv, "dbextra");
- if (kv != NULL && kv->val != NULL) {
- dbextra = kv->val;
- }
-
-
-
/* redirect stdout and stderr to a new pair of fds for
* logging help */
close(pfdo[0]);
@@ -496,252 +582,159 @@ forkMserver(char *database, sabdb** stat
dup2(pfde[1], 2);
close(pfde[1]);
- mport = (unsigned int)getConfNum(_mero_props, "port");
-
- /* ok, now exec that mserver we want */
- snprintf(dbpath, sizeof(dbpath),
- "--dbpath=%s/%s", sabdbfarm, database);
- snprintf(vaultkey, sizeof(vaultkey),
- "monet_vault_key=%s/.vaultkey",
(*stats)->path);
- snprintf(muri, sizeof(muri),
- "merovingian_uri=mapi:monetdb://%s:%u/%s",
- _mero_hostname, mport, database);
- argv[c++] = _mero_mserver;
- argv[c++] = dbpath;
- argv[c++] = "--set"; argv[c++] = muri;
- if (dbextra != NULL) {
- snprintf(dbextra_path, sizeof(dbextra_path),
- "--dbextra=%s", dbextra);
- argv[c++] = dbextra_path;
- }
- if (mydoproxy == 1) {
- struct sockaddr_un s; /* only for sizeof(s.sun_path) :(
*/
- argv[c++] = "--set"; argv[c++] = "mapi_open=false";
- /* we "proxy", so we can just solely use UNIX domain
sockets
- * internally. Before we hit our head, check if we can
- * actually use a UNIX socket (due to pathlength) */
- if (strlen((*stats)->path) + 11 < sizeof(s.sun_path)) {
- snprintf(port, sizeof(port), "mapi_port=0");
- snprintf(usock, sizeof(usock),
"mapi_usock=%s/.mapi.sock",
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list