about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--cmogstored.c1
-rw-r--r--cmogstored.h1
-rw-r--r--svc.c29
-rw-r--r--svc_dev.c5
4 files changed, 35 insertions, 1 deletions
diff --git a/cmogstored.c b/cmogstored.c
index 64b932d..31bdd85 100644
--- a/cmogstored.c
+++ b/cmogstored.c
@@ -419,6 +419,7 @@ static void fork_worker(unsigned worker_id)
                 mog_process_register(pid, worker_id);
         } else if (pid == 0) {
                 mog_process_reset();
+                mog_svc_each(mog_svc_atfork_child, &parent);
 
                 /* worker will call mog_intr_enable() later in notify loop */
                 run_worker(parent);
diff --git a/cmogstored.h b/cmogstored.h
index 3c1801c..1006fc3 100644
--- a/cmogstored.h
+++ b/cmogstored.h
@@ -371,6 +371,7 @@ bool mog_svc_start_each(void *svc_ptr, void *have_mgmt_ptr);
 void mog_svc_thrpool_rescale(struct mog_svc *, unsigned ndev_new);
 void mog_svc_aio_threads_enqueue(struct mog_svc *, unsigned nr);
 void mog_svc_aio_threads_handler(void);
+bool mog_svc_atfork_child(void *svc_ptr, void *parent);
 
 /* dev.c */
 struct mog_dev *mog_dev_for(struct mog_svc *, uint32_t mog_devid, bool update);
diff --git a/svc.c b/svc.c
index 4a44493..86f69db 100644
--- a/svc.c
+++ b/svc.c
@@ -69,6 +69,35 @@ static void svc_once(void)
         atexit(svc_atexit);
 }
 
+bool mog_svc_atfork_child(void *svc_ptr, void *parent)
+{
+        struct mog_svc *svc = svc_ptr;
+        pid_t ppid = *((pid_t *)parent);
+        const char *failfn;
+
+        if (closedir(svc->dir) < 0) {
+                failfn = "closedir";
+                goto err;
+        }
+
+        svc->dir = opendir(svc->docroot);
+        if (svc->dir == NULL) {
+                failfn = "opendir";
+                goto err;
+        }
+
+        svc->docroot_fd = dirfd(svc->dir);
+        if (svc->docroot_fd < 0) {
+                failfn = "dirfd";
+                goto err;
+        }
+        return true;
+err:
+        syslog(LOG_ERR, "%s(%s) failed with: %m", failfn, svc->docroot);
+        kill(ppid, SIGTERM);
+        return false;
+}
+
 struct mog_svc * mog_svc_new(const char *docroot)
 {
         struct mog_svc *svc;
diff --git a/svc_dev.c b/svc_dev.c
index b2beec3..b6a1e71 100644
--- a/svc_dev.c
+++ b/svc_dev.c
@@ -129,7 +129,10 @@ static int svc_scandev(struct mog_svc *svc, unsigned *nr, mog_scandev_cb cb)
 
                 switch (hash_insert_if_absent(devhash, dev, NULL)) {
                 case 0:
-                        free(dev);
+                        /* do not free dev, it is in svc->by_mog_devid */
+                        syslog(LOG_ERR,
+                               "%s/%s seen twice in readdir (BUG?)",
+                               svc->docroot, ent->d_name);
                         break;
                 case 1:
                         (*nr)++;