src/cxx_supportlib/ProcessManagement/Spawn.cpp in passenger-5.3.4 vs src/cxx_supportlib/ProcessManagement/Spawn.cpp in passenger-5.3.5

- old
+ new

@@ -1,8 +1,8 @@ /* * Phusion Passenger - https://www.phusionpassenger.com/ - * Copyright (c) 2010-2017 Phusion Holding B.V. + * Copyright (c) 2010-2018 Phusion Holding B.V. * * "Passenger", "Phusion Passenger" and "Union Station" are registered * trademarks of Phusion Holding B.V. * * Permission is hereby granted, free of charge, to any person obtaining a copy @@ -31,10 +31,11 @@ #include <signal.h> #include <boost/thread.hpp> #include <oxt/system_calls.hpp> #include <string> +#include <algorithm> #include <cerrno> #include <ProcessManagement/Spawn.h> #include <ProcessManagement/Utils.h> #include <StaticString.h> @@ -108,11 +109,11 @@ } } void runCommandAndCaptureOutput(const char **command, SubprocessInfo &info, - string &output, bool killSubprocessOnInterruption, + SubprocessOutput &output, size_t maxSize, bool killSubprocessOnInterruption, const boost::function<void ()> &afterFork, const boost::function<void (const char **command, int errcode)> &onExecFail) { pid_t waitRet; int e, waitStatus; @@ -138,19 +139,21 @@ _exit(1); } else if (info.pid == -1) { e = errno; throw SystemException("Cannot fork() a new process", e); } else { - bool done = false; + size_t totalRead = 0; + output.eof = false; p[1].close(); - while (!done) { + while (totalRead < maxSize) { char buf[1024 * 4]; ssize_t ret; try { - ret = syscalls::read(p[0], buf, sizeof(buf)); + ret = syscalls::read(p[0], buf, + std::min<size_t>(sizeof(buf), maxSize - totalRead)); } catch (const boost::thread_interrupted &) { if (killSubprocessOnInterruption) { boost::this_thread::disable_syscall_interruption dsi; syscalls::kill(SIGKILL, info.pid); syscalls::waitpid(info.pid, NULL, 0); @@ -164,12 +167,16 @@ syscalls::kill(SIGKILL, info.pid); syscalls::waitpid(info.pid, NULL, 0); } throw SystemException(string("Cannot read output from the '") + command[0] + "' command", e); + } else if (ret == 0) { + output.eof = true; + break; + } else { + totalRead += ret; + output.data.append(buf, ret); } - done = ret == 0; - output.append(buf, ret); } p[0].close(); try { waitRet = syscalls::waitpid(info.pid, &waitStatus, 0);