feat(Process): Add options to disable STDIO in child process #3867

This commit is contained in:
Alex Fabijanic 2023-01-23 12:23:03 +01:00
parent feee864950
commit 4ceb731bba
9 changed files with 94 additions and 28 deletions

View File

@ -98,7 +98,7 @@ public:
/// Returns the number of seconds spent by the
/// current process in user and kernel mode.
static ProcessHandle launch(const std::string& command, const Args& args);
static ProcessHandle launch(const std::string& command, const Args& args, int options = 0);
/// Creates a new process for the given command and returns
/// a ProcessHandle of the new process. The given arguments are
/// passed to the command on the command line.
@ -106,7 +106,8 @@ public:
static ProcessHandle launch(
const std::string& command,
const Args& args,
const std::string& initialDirectory);
const std::string& initialDirectory,
int options = 0);
/// Creates a new process for the given command and returns
/// a ProcessHandle of the new process. The given arguments are
/// passed to the command on the command line.
@ -117,7 +118,8 @@ public:
const Args& args,
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe);
Pipe* errPipe,
int options = 0);
/// Creates a new process for the given command and returns
/// a ProcessHandle of the new process. The given arguments are
/// passed to the command on the command line.
@ -150,7 +152,8 @@ public:
const std::string& initialDirectory,
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe);
Pipe* errPipe,
int options = 0);
/// Creates a new process for the given command and returns
/// a ProcessHandle of the new process. The given arguments are
/// passed to the command on the command line.
@ -184,7 +187,8 @@ public:
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe,
const Env& env);
const Env& env,
int options = 0);
/// Creates a new process for the given command and returns
/// a ProcessHandle of the new process. The given arguments are
/// passed to the command on the command line.
@ -202,7 +206,8 @@ public:
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe,
const Env& env);
const Env& env,
int options = 0);
/// Creates a new process for the given command and returns
/// a ProcessHandle of the new process. The given arguments are
/// passed to the command on the command line.

View File

@ -0,0 +1,44 @@
//
// ProcessOptions.h
//
// Library: Foundation
// Package: Processes
// Module: ProcessOptions
//
// Definition of the ProcessOptions class.
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#ifndef Foundation_ProcessOptions_INCLUDED
#define Foundation_ProcessOptions_INCLUDED
#include "Poco/Foundation.h"
namespace Poco {
enum ProcessOptions
/// Options to configure child process behavior.
{
PROCESS_CLOSE_STDIN = 1,
/// Causes the child process STDIN to be closed.
PROCESS_CLOSE_STDOUT = 2,
/// Causes the child process STDOUT to be closed.
PROCESS_CLOSE_STDERR = 4,
/// Causes the child process STDERR to be closed.
};
} // namespace Poco
#endif // Foundation_ProcessOptions_INCLUDED

View File

@ -62,7 +62,8 @@ public:
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe,
const EnvImpl& env);
const EnvImpl& env,
int options = 0);
static void killImpl(ProcessHandleImpl& handle);
static void killImpl(PIDImpl pid);
static bool isRunningImpl(const ProcessHandleImpl& handle);
@ -77,7 +78,8 @@ private:
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe,
const EnvImpl& env);
const EnvImpl& env,
int options = 0);
};

View File

@ -68,7 +68,8 @@ public:
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe,
const EnvImpl& env);
const EnvImpl& env,
int options = 0);
static void killImpl(ProcessHandleImpl& handle);
static void killImpl(PIDImpl pid);
static bool isRunningImpl(const ProcessHandleImpl& handle);

View File

@ -68,7 +68,8 @@ public:
Pipe* inPipe,
Pipe* outPipe,
Pipe* errPipe,
const EnvImpl& env);
const EnvImpl& env,
int options = 0);
static void killImpl(ProcessHandleImpl& handle);
static void killImpl(PIDImpl pid);
static bool isRunningImpl(const ProcessHandleImpl& handle);

View File

@ -119,50 +119,50 @@ int ProcessHandle::tryWait() const
//
// Process
//
ProcessHandle Process::launch(const std::string& command, const Args& args)
ProcessHandle Process::launch(const std::string& command, const Args& args, int options)
{
std::string initialDirectory;
Env env;
return ProcessHandle(launchImpl(command, args, initialDirectory, 0, 0, 0, env));
return ProcessHandle(launchImpl(command, args, initialDirectory, 0, 0, 0, env, options));
}
ProcessHandle Process::launch(const std::string& command, const Args& args, const std::string& initialDirectory)
ProcessHandle Process::launch(const std::string& command, const Args& args, const std::string& initialDirectory, int options)
{
Env env;
return ProcessHandle(launchImpl(command, args, initialDirectory, 0, 0, 0, env));
return ProcessHandle(launchImpl(command, args, initialDirectory, 0, 0, 0, env, options));
}
ProcessHandle Process::launch(const std::string& command, const Args& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe)
ProcessHandle Process::launch(const std::string& command, const Args& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, int options)
{
poco_assert (inPipe == 0 || (inPipe != outPipe && inPipe != errPipe));
std::string initialDirectory;
Env env;
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env));
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env, options));
}
ProcessHandle Process::launch(const std::string& command, const Args& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe)
ProcessHandle Process::launch(const std::string& command, const Args& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, int options)
{
poco_assert (inPipe == 0 || (inPipe != outPipe && inPipe != errPipe));
Env env;
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env));
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env, options));
}
ProcessHandle Process::launch(const std::string& command, const Args& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const Env& env)
ProcessHandle Process::launch(const std::string& command, const Args& args, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const Env& env, int options)
{
poco_assert (inPipe == 0 || (inPipe != outPipe && inPipe != errPipe));
std::string initialDirectory;
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env));
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env, options));
}
ProcessHandle Process::launch(const std::string& command, const Args& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const Env& env)
ProcessHandle Process::launch(const std::string& command, const Args& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const Env& env, int options)
{
poco_assert (inPipe == 0 || (inPipe != outPipe && inPipe != errPipe));
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env));
return ProcessHandle(launchImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env, options));
}

View File

@ -12,6 +12,7 @@
//
#include "Poco/ProcessOptions.h"
#include "Poco/Process_UNIX.h"
#include "Poco/Exception.h"
#include "Poco/NumberFormatter.h"
@ -112,7 +113,7 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
}
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env, int options)
{
#if defined(__QNX__)
if (initialDirectory.empty())
@ -156,21 +157,24 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
throw SystemException("cannot spawn", command);
if (inPipe) inPipe->close(Pipe::CLOSE_READ);
if (options & PROCESS_CLOSE_STDIN) close(STDIN_FILENO);
if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
if (options & PROCESS_CLOSE_STDOUT) close(STDOUT_FILENO);
if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
if (options & PROCESS_CLOSE_STDERR) close(STDERR_FILENO);
return new ProcessHandleImpl(pid);
}
else
{
return launchByForkExecImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env);
return launchByForkExecImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env, options);
}
#else
return launchByForkExecImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env);
return launchByForkExecImpl(command, args, initialDirectory, inPipe, outPipe, errPipe, env, options);
#endif
}
ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env, int options)
{
#if !defined(POCO_NO_FORK_EXEC)
// On some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number,
@ -222,11 +226,15 @@ ProcessHandleImpl* ProcessImpl::launchByForkExecImpl(const std::string& command,
dup2(inPipe->readHandle(), STDIN_FILENO);
inPipe->close(Pipe::CLOSE_BOTH);
}
if (options & PROCESS_CLOSE_STDIN) close(STDIN_FILENO);
// outPipe and errPipe may be the same, so we dup first and close later
if (outPipe) dup2(outPipe->writeHandle(), STDOUT_FILENO);
if (errPipe) dup2(errPipe->writeHandle(), STDERR_FILENO);
if (outPipe) outPipe->close(Pipe::CLOSE_BOTH);
if (options & PROCESS_CLOSE_STDOUT) close(STDOUT_FILENO);
if (errPipe) errPipe->close(Pipe::CLOSE_BOTH);
if (options & PROCESS_CLOSE_STDERR) close(STDERR_FILENO);
// close all open file descriptors other than stdin, stdout, stderr
long fdMax = sysconf(_SC_OPEN_MAX);
// on some systems, sysconf(_SC_OPEN_MAX) returns a ridiculously high number

View File

@ -12,6 +12,7 @@
//
#include "Poco/ProcessOptions.h"
#include "Poco/Process_WIN32U.h"
#include "Poco/Exception.h"
#include "Poco/NumberFormatter.h"
@ -227,7 +228,7 @@ std::string ProcessImpl::escapeArg(const std::string& arg)
}
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env, int options)
{
std::string commandLine = escapeArg(command);
for (const auto& a: args)
@ -279,6 +280,8 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
{
startupInfo.hStdInput = 0;
}
if (options & PROCESS_CLOSE_STDIN) CloseHandle(GetStdHandle(STD_INPUT_HANDLE));
// outPipe may be the same as errPipe, so we duplicate first and close later.
if (outPipe)
{
@ -309,7 +312,9 @@ ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const Arg
startupInfo.hStdError = 0;
}
if (outPipe) outPipe->close(Pipe::CLOSE_WRITE);
if (options & PROCESS_CLOSE_STDOUT) CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
if (errPipe) errPipe->close(Pipe::CLOSE_WRITE);
if (options & PROCESS_CLOSE_STDERR) CloseHandle(GetStdHandle(STD_ERROR_HANDLE));
if (mustInheritHandles)
{

View File

@ -118,7 +118,7 @@ void ProcessImpl::timesImpl(long& userTime, long& kernelTime)
}
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env)
ProcessHandleImpl* ProcessImpl::launchImpl(const std::string& command, const ArgsImpl& args, const std::string& initialDirectory, Pipe* inPipe, Pipe* outPipe, Pipe* errPipe, const EnvImpl& env, int options)
{
std::wstring ucommand;
UnicodeConverter::toUTF16(command, ucommand);