mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: provide system() command with CStringList
- allows (for example) splitting a user string on whitespace and passing this to system as a list of arguments, thus bypassing any implicit use of 'sh'. - system() with optional background, for spawning processes.
This commit is contained in:
@ -1406,7 +1406,11 @@ static int waitpid(const pid_t pid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Foam::system(const std::string& command)
|
int Foam::system
|
||||||
|
(
|
||||||
|
const std::string& command,
|
||||||
|
const bool background
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if (command.empty())
|
if (command.empty())
|
||||||
{
|
{
|
||||||
@ -1446,12 +1450,24 @@ int Foam::system(const std::string& command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// in parent - blocking wait
|
// In parent:
|
||||||
|
|
||||||
|
if (background)
|
||||||
|
{
|
||||||
|
// Started as background process
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// blocking wait for the child
|
||||||
return waitpid(child_pid);
|
return waitpid(child_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int Foam::system(const Foam::UList<Foam::string>& command)
|
int Foam::system
|
||||||
|
(
|
||||||
|
const CStringList& command,
|
||||||
|
const bool background
|
||||||
|
)
|
||||||
{
|
{
|
||||||
const int argc = command.size();
|
const int argc = command.size();
|
||||||
|
|
||||||
@ -1478,7 +1494,70 @@ int Foam::system(const Foam::UList<Foam::string>& command)
|
|||||||
|
|
||||||
if (child_pid == 0)
|
if (child_pid == 0)
|
||||||
{
|
{
|
||||||
// in child:
|
// In child:
|
||||||
|
// Need command and arguments separately.
|
||||||
|
// args is a nullptr-terminated list of c-strings
|
||||||
|
|
||||||
|
// execvp uses the current environ
|
||||||
|
(void) ::execvp(command[0], command.strings(1));
|
||||||
|
|
||||||
|
// obviously failed, since exec should not return at all
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "exec(" << command[0] << ", ...) failed"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// In parent:
|
||||||
|
|
||||||
|
if (background)
|
||||||
|
{
|
||||||
|
// Started as background process
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// blocking wait for the child
|
||||||
|
return waitpid(child_pid);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Foam::system
|
||||||
|
(
|
||||||
|
const Foam::UList<Foam::string>& command,
|
||||||
|
const bool background
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// In the future simply call the CStringList version:
|
||||||
|
//
|
||||||
|
// const CStringList cmd(command);
|
||||||
|
// return Foam::system(cmd, background);
|
||||||
|
|
||||||
|
const int argc = command.size();
|
||||||
|
|
||||||
|
if (!argc)
|
||||||
|
{
|
||||||
|
// Treat an empty command as a successful no-op.
|
||||||
|
// For consistency with POSIX (man sh) behaviour for (sh -c command),
|
||||||
|
// which is what is mostly being replicated here.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: use vfork, not fork!
|
||||||
|
// vfork behaves more like a thread and avoids copy-on-write problems
|
||||||
|
// triggered by fork.
|
||||||
|
// The normal system() command has a fork buried in it that causes
|
||||||
|
// issues with infiniband and openmpi etc.
|
||||||
|
pid_t child_pid = ::vfork();
|
||||||
|
if (child_pid == -1)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "vfork() failed for system command " << command[0]
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child_pid == 0)
|
||||||
|
{
|
||||||
|
// In child:
|
||||||
// Need command and arguments separately.
|
// Need command and arguments separately.
|
||||||
// args is a nullptr-terminated list of c-strings
|
// args is a nullptr-terminated list of c-strings
|
||||||
|
|
||||||
@ -1498,7 +1577,15 @@ int Foam::system(const Foam::UList<Foam::string>& command)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// in parent - blocking wait
|
// In parent:
|
||||||
|
|
||||||
|
if (background)
|
||||||
|
{
|
||||||
|
// Started as background process
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// blocking wait for the child
|
||||||
return waitpid(child_pid);
|
return waitpid(child_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -46,6 +46,10 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Forward declarations
|
||||||
|
class CStringList;
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
//- Return the PID of this process
|
//- Return the PID of this process
|
||||||
@ -206,14 +210,32 @@ bool ping(const std::string& host, const label timeOut=10);
|
|||||||
// Uses vfork/execl internally.
|
// Uses vfork/execl internally.
|
||||||
// Where possible, use the list version instead.
|
// Where possible, use the list version instead.
|
||||||
//
|
//
|
||||||
// Treats an empty command as a successful no-op.
|
// \param background return immediately to parent process instead of waiting
|
||||||
int system(const std::string& command);
|
// for the child. Can be used (with moderation) to create background
|
||||||
|
// processes.
|
||||||
|
//
|
||||||
|
// \note treats an empty command as a successful no-op.
|
||||||
|
int system(const std::string& command, const bool background=false);
|
||||||
|
|
||||||
//- Execute the specified command with arguments.
|
//- Execute the specified command with arguments.
|
||||||
// Uses vfork/execvp internally
|
// Uses vfork/execvp internally
|
||||||
//
|
//
|
||||||
// Treats an empty command as a successful no-op.
|
// \param background return immediately to parent process instead of waiting
|
||||||
int system(const UList<string>& command);
|
// for the child. Can be used (with moderation) to create background
|
||||||
|
// processes.
|
||||||
|
//
|
||||||
|
// \note treats an empty command as a successful no-op.
|
||||||
|
int system(const UList<string>& command, const bool background=false);
|
||||||
|
|
||||||
|
//- Execute the specified command with arguments.
|
||||||
|
// Uses vfork/execvp internally
|
||||||
|
//
|
||||||
|
// \param background return immediately to parent process instead of waiting
|
||||||
|
// for the child. Can be used (with moderation) to create background
|
||||||
|
// processes.
|
||||||
|
//
|
||||||
|
// \note treats an empty command as a successful no-op.
|
||||||
|
int system(const CStringList& command, const bool background=false);
|
||||||
|
|
||||||
//- Open a shared library and return handle to library.
|
//- Open a shared library and return handle to library.
|
||||||
// Print error message if library cannot be loaded (suppress with check=true)
|
// Print error message if library cannot be loaded (suppress with check=true)
|
||||||
|
|||||||
Reference in New Issue
Block a user