about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <normalperson@yhbt.net>2013-02-07 20:29:47 +0000
committerEric Wong <normalperson@yhbt.net>2013-02-07 20:29:47 +0000
commit4f45f562180489a97a4572ebd3822e9f15289bd6 (patch)
tree78be2c75cc7b92da8ff5b101664a9328ffe61323
parent315487f70c90b117aa4e9d63bbb21abae8af80ab (diff)
downloadcmogstored-4f45f562180489a97a4572ebd3822e9f15289bd6.tar.gz
Pthreads implementations do not require mutexes be in a
consistent/usable state in a forked child
Since we don't need the mutex in a single-threaded forked
child, we can just skip it and avoid reinitializing it
entirely.
-rw-r--r--cmogstored.h1
-rw-r--r--svc.c25
-rw-r--r--upgrade.c18
3 files changed, 27 insertions, 17 deletions
diff --git a/cmogstored.h b/cmogstored.h
index 1b3d1be..eafbae6 100644
--- a/cmogstored.h
+++ b/cmogstored.h
@@ -309,6 +309,7 @@ void mog_set_maxconns(unsigned long);
 struct mog_svc *mog_svc_new(const char *docroot);
 typedef int (*mog_scandev_cb)(const struct mog_dev *, struct mog_svc *);
 size_t mog_svc_each(Hash_processor processor, void *data);
+void mog_svc_upgrade_prepare(void);
 
 /* dev.c */
 struct mog_dev * mog_dev_new(struct mog_svc *, uint32_t mog_devid);
diff --git a/svc.c b/svc.c
index 28e76d3..1b5a812 100644
--- a/svc.c
+++ b/svc.c
@@ -118,3 +118,28 @@ size_t mog_svc_each(Hash_processor processor, void *data)
 
         return rv;
 }
+
+static bool cloexec_disable(int fd)
+{
+        if (fd >= 0)
+                CHECK(int, 0, mog_set_cloexec(fd, false));
+        return true;
+}
+
+static bool svc_cloexec_off_i(void *svcptr, void *unused)
+{
+        struct mog_svc *svc = svcptr;
+
+        return (cloexec_disable(svc->mgmt_fd)
+                && cloexec_disable(svc->http_fd)
+                && cloexec_disable(svc->httpget_fd));
+}
+
+/*
+ * Only call this from a freshly forked upgrade child process.
+ * This holds no locks to avoid potential deadlocks in post-fork mutexes
+ */
+void mog_svc_upgrade_prepare(void)
+{
+        (void)hash_do_for_each(by_docroot, svc_cloexec_off_i, NULL);
+}
diff --git a/upgrade.c b/upgrade.c
index 4083b25..98de363 100644
--- a/upgrade.c
+++ b/upgrade.c
@@ -81,22 +81,6 @@ static bool svc_emit_fd_i(void *svcptr, void *_fp)
                 && emit_fd(fp, svc->httpget_fd));
 }
 
-static bool cloexec_disable(int fd)
-{
-        if (fd >= 0)
-                CHECK(int, 0, mog_set_cloexec(fd, false));
-        return true;
-}
-
-static bool svc_cloexec_off_i(void *svcptr, void *unused)
-{
-        struct mog_svc *svc = svcptr;
-
-        return (cloexec_disable(svc->mgmt_fd)
-                && cloexec_disable(svc->http_fd)
-                && cloexec_disable(svc->httpget_fd));
-}
-
 /* returns the PID of the newly spawned child */
 pid_t mog_upgrade_spawn(void)
 {
@@ -145,7 +129,7 @@ pid_t mog_upgrade_spawn(void)
                 /* CMOGSTORED_FD= is set here */
                 CHECK(int, 0, putenv(dst));
 
-                mog_svc_each(svc_cloexec_off_i, NULL);
+                mog_svc_upgrade_prepare();
                 mog_intr_enable();
                 execvp(start.argv[0], start.argv);
                 die_errno("execvp %s", start.argv[0]);