From: Kefu Chai Date: Fri, 28 Aug 2015 13:01:53 +0000 (-0700) Subject: common/SubProcess: silence compiler warnings X-Git-Tag: v9.1.0~234^2 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=afa92e5743832f8fd3956bd1eac695daa07ad5ff;p=ceph.git common/SubProcess: silence compiler warnings * 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 --- diff --git a/src/common/SubProcess.h b/src/common/SubProcess.h index 3d739849193d..60dd4aef6720 100644 --- a/src/common/SubProcess.h +++ b/src/common/SubProcess.h @@ -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); }