]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph.git/commitdiff
common/SubProcess: silence compiler warnings 5693/head
authorKefu Chai <kchai@redhat.com>
Fri, 28 Aug 2015 13:01:53 +0000 (06:01 -0700)
committerKefu Chai <kchai@redhat.com>
Fri, 28 Aug 2015 13:09:21 +0000 (06:09 -0700)
* the STD{IN,OUT,ERR}_FILENO are closed when being dup2'ed so we
  can not write to cout or cerr in child processes, as these
  fstream are still holding the old references.
* to silence every write(2) call is tedious. better off overwriting
  the raw buffer in cerr and cout ostreams

Fixes: #12730
Signed-off-by: Kefu Chai <kchai@redhat.com>
src/common/SubProcess.h

index 3d739849193d4ee424c13ceb1de41ff32e27e845..60dd4aef67205bebc73dc47ec1446a5110be6152 100644 (file)
@@ -212,6 +212,25 @@ const char* SubProcess::err() const {
   return errstr.str().c_str();
 }
 
+class fd_buf : public std::streambuf {
+  int fd;
+public:
+  fd_buf (int fd) : fd(fd)
+  {}
+protected:
+  int_type overflow (int_type c) override {
+    if (c == EOF) return EOF;
+    char buf = c;
+    if (write (fd, &buf, 1) != 1) {
+      return EOF;
+    }
+    return c;
+  }
+  std::streamsize xsputn (const char* s, std::streamsize count) override {
+    return write(fd, s, count);
+  }
+};
+
 int SubProcess::spawn() {
   assert(!is_spawned());
   assert(stdin_pipe_out_fd == -1);
@@ -255,10 +274,14 @@ int SubProcess::spawn() {
     if (opipe[OUT] != -1 && opipe[OUT] != STDOUT_FILENO) {
       ::dup2(opipe[OUT], STDOUT_FILENO);
       close(opipe[OUT]);
+      static fd_buf buf(STDOUT_FILENO);
+      std::cout.rdbuf(&buf);
     }
     if (epipe[OUT] != -1 && epipe[OUT] != STDERR_FILENO) {
       ::dup2(epipe[OUT], STDERR_FILENO);
       close(epipe[OUT]);
+      static fd_buf buf(STDERR_FILENO);
+      std::cerr.rdbuf(&buf);
     }
 
     int maxfd = sysconf(_SC_OPEN_MAX);
@@ -307,9 +330,7 @@ void SubProcess::exec() {
   int ret = execvp(cmd.c_str(), (char * const *)&args[0]);
   assert(ret == -1);
 
-  std::ostringstream err;
-  err << cmd << ": exec failed: " << cpp_strerror(errno) << "\n";
-  write(STDERR_FILENO, err.str().c_str(), err.str().size());
+  std::cerr << cmd << ": exec failed: " << cpp_strerror(errno) << "\n";
   _exit(EXIT_FAILURE);
 }
 
@@ -363,24 +384,23 @@ void SubProcessTimed::exec() {
   }
 
   sigset_t mask, oldmask;
-  std::ostringstream err;
   int pid;
 
   // Restore default action for SIGTERM in case the parent process decided
   // to ignore it.
   if (signal(SIGTERM, SIG_DFL) == SIG_ERR) {
-    err << cmd << ": signal failed: " << cpp_strerror(errno) << "\n";
+    std::cerr << cmd << ": signal failed: " << cpp_strerror(errno) << "\n";
     goto fail_exit;
   }
   // Because SIGCHLD is ignored by default, setup dummy handler for it,
   // so we can mask it.
   if (signal(SIGCHLD, dummy_sighandler) == SIG_ERR) {
-    err << cmd << ": signal failed: " << cpp_strerror(errno) << "\n";
+    std::cerr << cmd << ": signal failed: " << cpp_strerror(errno) << "\n";
     goto fail_exit;
   }
   // Setup timeout handler.
   if (signal(SIGALRM, timeout_sighandler) == SIG_ERR) {
-    err << cmd << ": signal failed: " << cpp_strerror(errno) << "\n";
+    std::cerr << cmd << ": signal failed: " << cpp_strerror(errno) << "\n";
     goto fail_exit;
   }
   // Block interesting signals.
@@ -390,21 +410,21 @@ void SubProcessTimed::exec() {
   sigaddset(&mask, SIGCHLD);
   sigaddset(&mask, SIGALRM);
   if (sigprocmask(SIG_SETMASK, &mask, &oldmask) == -1) {
-    err << cmd << ": sigprocmask failed: " << cpp_strerror(errno) << "\n";
+    std::cerr << cmd << ": sigprocmask failed: " << cpp_strerror(errno) << "\n";
     goto fail_exit;
   }
 
   pid = fork();
 
   if (pid == -1) {
-    err << cmd << ": fork failed: " << cpp_strerror(errno) << "\n";
+    std::cerr << cmd << ": fork failed: " << cpp_strerror(errno) << "\n";
     goto fail_exit;
   }
 
   if (pid == 0) { // Child
     // Restore old sigmask.
     if (sigprocmask(SIG_SETMASK, &oldmask, NULL) == -1) {
-      err << cmd << ": sigprocmask failed: " << cpp_strerror(errno) << "\n";
+      std::cerr << cmd << ": sigprocmask failed: " << cpp_strerror(errno) << "\n";
       goto fail_exit;
     }
     (void)setpgid(0, 0); // Become process group leader.
@@ -418,48 +438,45 @@ void SubProcessTimed::exec() {
   for (;;) {
     int signo;
     if (sigwait(&mask, &signo) == -1) {
-      err << cmd << ": sigwait failed: " << cpp_strerror(errno) << "\n";
+      std::cerr << cmd << ": sigwait failed: " << cpp_strerror(errno) << "\n";
       goto fail_exit;
     }
     switch (signo) {
     case SIGCHLD:
       int status;
       if (waitpid(pid, &status, WNOHANG) == -1) {
-       err << cmd << ": waitpid failed: " << cpp_strerror(errno) << "\n";
+       std::cerr << cmd << ": waitpid failed: " << cpp_strerror(errno) << "\n";
        goto fail_exit;
       }
-      write(STDERR_FILENO, err.str().c_str(), err.str().size());
       if (WIFEXITED(status))
        _exit(WEXITSTATUS(status));
       if (WIFSIGNALED(status))
        _exit(128 + WTERMSIG(status));
-      err << cmd << ": unknown status returned\n";
+      std::cerr << cmd << ": unknown status returned\n";
       goto fail_exit;
     case SIGINT:
     case SIGTERM:
       // Pass SIGINT and SIGTERM, which are usually used to terminate
       // a process, to the child.
       if (::kill(pid, signo) == -1) {
-       err << cmd << ": kill failed: " << cpp_strerror(errno) << "\n";
+       std::cerr << cmd << ": kill failed: " << cpp_strerror(errno) << "\n";
        goto fail_exit;
       }
       continue;
     case SIGALRM:
-      err << cmd << ": timed out (" << timeout << " sec)\n";
-      write(STDERR_FILENO, err.str().c_str(), err.str().size());
+      std::cerr << cmd << ": timed out (" << timeout << " sec)\n";
       if (::killpg(pid, sigkill) == -1) {
-       err << cmd << ": kill failed: " << cpp_strerror(errno) << "\n";
+       std::cerr << cmd << ": kill failed: " << cpp_strerror(errno) << "\n";
        goto fail_exit;
       }
       continue;
     default:
-      err << cmd << ": sigwait: invalid signal: " << signo << "\n";
+      std::cerr << cmd << ": sigwait: invalid signal: " << signo << "\n";
       goto fail_exit;
     }
   }
 
 fail_exit:
-  write(STDERR_FILENO, err.str().c_str(), err.str().size());
   _exit(EXIT_FAILURE);
 }