about summary refs log tree commit homepage
diff options
context:
space:
mode:
-rw-r--r--cmogstored.h10
-rw-r--r--configure.ac1
-rw-r--r--iostat_process.c6
-rw-r--r--upgrade.c8
4 files changed, 19 insertions, 6 deletions
diff --git a/cmogstored.h b/cmogstored.h
index 5aa7c01..4bb0716 100644
--- a/cmogstored.h
+++ b/cmogstored.h
@@ -360,6 +360,16 @@ void mog_oom_if_null(const void *);
 
 #define warn(...) error(0, 0, __VA_ARGS__)
 
+/*
+ * vfork is poorly-specified, but at least on Linux it improves
+ * performance when used for spawning iostat processes
+ */
+#if defined(HAVE_VFORK) && defined(__linux__)
+#  define mog_fork_for_exec() vfork()
+#else
+#  define mog_fork_for_exec() fork()
+#endif
+
 /* maxconns.c */
 void mog_set_maxconns(unsigned long);
 
diff --git a/configure.ac b/configure.ac
index 8bd98e2..0d551c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,6 +51,7 @@ AC_CHECK_FUNCS([ioctl])
 AC_CHECK_FUNCS([sendfile])
 AC_CHECK_FUNCS([open_memstream])
 AC_CHECK_FUNCS([posix_fadvise])
+AC_CHECK_FUNCS([vfork])
 
 dnl need LIBS=-lfreebsd-glue (but not CFLAGS=-I/usr/include/freebsd)
 AC_CHECK_FUNCS([bsd_sendfile])
diff --git a/iostat_process.c b/iostat_process.c
index 90a291f..4d7dfbf 100644
--- a/iostat_process.c
+++ b/iostat_process.c
@@ -65,7 +65,7 @@ static void dup2_or_die(int oldfd, int newfd, const char *errdesc)
 
         if (rc < 0) {
                 syslog(LOG_CRIT, "dup2(%s) failed: %m", errdesc);
-                abort();
+                _exit(1);
         }
 }
 
@@ -96,7 +96,7 @@ static pid_t iostat_fork_exec(int out_fd)
 
         cmd = exec_cmd(cmd);
 
-        iostat_pid = fork();
+        iostat_pid = mog_fork_for_exec();
         if (iostat_pid < 0) {
                 syslog(LOG_ERR, "fork() for iostat failed: %m");
         } else if (iostat_pid > 0) {
@@ -111,7 +111,7 @@ static pid_t iostat_fork_exec(int out_fd)
                 mog_intr_enable();
                 execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
                 syslog(LOG_CRIT, "execl(%s) failed: %m", cmd);
-                abort();
+                _exit(1);
         }
         mog_free(cmd);
         return iostat_pid;
diff --git a/upgrade.c b/upgrade.c
index 1311ebe..82a7b28 100644
--- a/upgrade.c
+++ b/upgrade.c
@@ -125,13 +125,14 @@ pid_t mog_upgrade_spawn(void)
 
         assert(dst[bytes - 1] == ',' && "not comma-terminated no listeners?");
         dst[bytes - 1] = '\0'; /* kill the last comma */
+        start.envp[0] = dst;
 
-        pid = fork();
+        pid = mog_fork_for_exec();
         if (pid == 0) {
-                start.envp[0] = dst;
                 mog_svc_upgrade_prepare();
                 execve(execfile, start.argv, start.envp);
-                die_errno("execve %s", execfile);
+                syslog(LOG_ERR, "execve %s failed for upgrade: %m", execfile);
+                _exit(2);
         } else if (pid > 0) {
                 mog_process_register(pid, MOG_PROC_UPGRADE);
                 syslog(LOG_INFO, "upgrade spawned PID:%d", pid);
@@ -143,6 +144,7 @@ out:
         /* find_in_path does not malloc if output == input */
         if (execfile != start.argv[0])
                 mog_free(execfile);
+        start.envp[0] = 0;
         free(dst);
 
         return pid;