diff --git a/applications/utilities/miscellaneous/foamHelp/helpTypes/helpType/helpType.C b/applications/utilities/miscellaneous/foamHelp/helpTypes/helpType/helpType.C index 68ae82fa50aedbbb131b462144a03944db07fd09..a5b217e87ee3c13b3cf56fb6c6acdb99ed36b755 100644 --- a/applications/utilities/miscellaneous/foamHelp/helpTypes/helpType/helpType.C +++ b/applications/utilities/miscellaneous/foamHelp/helpTypes/helpType/helpType.C @@ -151,7 +151,7 @@ void Foam::helpType::displayDoc Info<< "Source file: " << classDirectory.c_str() << classFile << nl << endl; - system(docBrowser); + Foam::system(docBrowser); } else { diff --git a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C index 3ac7b6f7668e3bae7451df7aa10be89c94106a10..51a3563f5e193897e8d61631f795b3ab68959024 100644 --- a/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C +++ b/applications/utilities/postProcessing/dataConversion/foamToVTK/foamToVTK.C @@ -1309,7 +1309,7 @@ int main(int argc, char *argv[]) + "_" + procFile.name() ); - if (system(cmd.c_str()) == -1) + if (Foam::system(cmd.c_str()) == -1) { WarningInFunction << "Could not execute command " << cmd << endl; diff --git a/applications/utilities/preProcessing/viewFactorsGen/viewFactorsGen.C b/applications/utilities/preProcessing/viewFactorsGen/viewFactorsGen.C index 11a8becd5adfb715bab67bce382afaa138149635..a8e20b188f685c9792dc87afae597d1ac7e2a9e9 100644 --- a/applications/utilities/preProcessing/viewFactorsGen/viewFactorsGen.C +++ b/applications/utilities/preProcessing/viewFactorsGen/viewFactorsGen.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -191,9 +191,15 @@ void writeRays str << "l " << vertI-1 << ' ' << vertI << nl; } } - string cmd("objToVTK " + fName + " " + fName.lessExt() + ".vtk"); - Pout<< "cmd:" << cmd << endl; - system(cmd); + str.flush(); + + DynamicList<string> cmd(3); + cmd.append("objToVTK"); + cmd.append(fName); + cmd.append(fName.lessExt() + ".vtk"); + + Pout<< "cmd: objToVTK " << fName.c_str() << endl; + Foam::system(cmd); } diff --git a/src/OSspecific/POSIX/POSIX.C b/src/OSspecific/POSIX/POSIX.C index 0b9a541d94083d0aa63f2b5641b300ae5ef64762..8ecdaeb3e22a01a98319c0ffc39c983b5f54700b 100644 --- a/src/OSspecific/POSIX/POSIX.C +++ b/src/OSspecific/POSIX/POSIX.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -38,6 +38,8 @@ Description #include "timer.H" #include "IFstream.H" #include "DynamicList.H" +#include "CStringList.H" +#include "SubList.H" #include <fstream> #include <cstdlib> @@ -49,6 +51,7 @@ Description #include <pwd.h> #include <errno.h> #include <sys/types.h> +#include <sys/wait.h> #include <sys/stat.h> #include <sys/socket.h> #include <netdb.h> @@ -1166,9 +1169,153 @@ bool Foam::ping(const string& hostname, const label timeOut) } +namespace Foam +{ +//! \cond fileScope +static int waitpid(const pid_t pid) +{ + // child status, return code from the exec etc. + int status = 0; + + // in parent - blocking wait + // modest treatment of signals (in child) + // treat 'stopped' like exit (suspend/continue) + while (true) + { + pid_t wpid = ::waitpid(pid, &status, WUNTRACED); + + if (wpid == -1) + { + FatalErrorInFunction + << "some error occurred in child" + << exit(FatalError); + break; + } + + if (WIFEXITED(status)) + { + // child exited, get its return status + return WEXITSTATUS(status); + } + + if (WIFSIGNALED(status)) + { + // child terminated by some signal + return WTERMSIG(status); + } + + if (WIFSTOPPED(status)) + { + // child stopped by some signal + return WSTOPSIG(status); + } + + FatalErrorInFunction + << "programming error, status from waitpid() not handled: " + << status + << exit(FatalError); + } + + return -1; // should not happen +} +//! \endcond +} + + int Foam::system(const std::string& command) { - return ::system(command.c_str()); + if (command.empty()) + { + // Treat an empty command as a successful no-op. + // From 'man sh' POSIX (man sh): + // "If the command_string operand is an empty string, + // sh shall exit with a zero exit status." + return 0; + } + + pid_t child_pid = ::vfork(); // NB: vfork, not fork! + if (child_pid == -1) + { + FatalErrorInFunction + << "vfork() failed for system command " << command + << exit(FatalError); + } + + if (child_pid == 0) + { + // in child + + // execl uses the current environ + (void) ::execl + ( + "/bin/sh", // Path of the shell + "sh", // Command-name (name for the shell) + "-c", // Read commands from the command_string operand. + command.c_str(), // Command string + reinterpret_cast<char *>(0) + ); + + // obviously failed, since exec should not return at all + FatalErrorInFunction + << "exec failed: " << command + << exit(FatalError); + } + + + // in parent - blocking wait + return waitpid(child_pid); +} + + +int Foam::system(const Foam::UList<Foam::string>& command) +{ + 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. + // args is a NULL-terminated list of c-strings + + CStringList args(SubList<string>(command, 0)); + if (argc > 1) + { + args.reset(SubList<string>(command, argc-1, 1)); + } + + // execvp uses the current environ + (void) ::execvp(command[0].c_str(), args.strings()); + + // obviously failed, since exec should not return at all + FatalErrorInFunction + << "exec(" << command[0] << ", ...) failed" + << exit(FatalError); + } + + + // in parent - blocking wait + return waitpid(child_pid); } diff --git a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C index 04932fceea3df03528217f4914fdb5a7e2f19021..19882241e3476f97abd621ffdd08de592bc9324a 100644 --- a/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C +++ b/src/OpenFOAM/db/dynamicLibrary/dynamicCode/dynamicCode.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -493,10 +493,17 @@ bool Foam::dynamicCode::copyOrCreateFiles(const bool verbose) const bool Foam::dynamicCode::wmakeLibso() const { - const Foam::string wmakeCmd("wmake -s libso " + this->codePath()); - Info<< "Invoking " << wmakeCmd << endl; + DynamicList<string> cmd(4); + cmd.append("wmake"); + cmd.append("-s"); + cmd.append("libso"); + cmd.append(this->codePath()); - if (Foam::system(wmakeCmd)) + // NOTE: could also resolve wmake command explicitly + // cmd[0] = stringOps::expand("$WM_PROJECT_DIR/wmake/wmake"); + + Info<< "Invoking wmake libso " << this->codePath().c_str() << endl; + if (Foam::system(cmd)) { return false; } diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index 5d391afaafe0d15044e096460cf4049e4639de53..8f489589b02f8370180af75c329f975dcdfad06c 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -1170,7 +1170,7 @@ void Foam::argList::displayDoc(bool source) const Info<< "Show documentation: " << docBrowser.c_str() << endl; - system(docBrowser); + Foam::system(docBrowser); } else { diff --git a/src/OpenFOAM/include/OSspecific.H b/src/OpenFOAM/include/OSspecific.H index d190f67045e2536e9b131f4a2e41ea292b310758..4adc48aeeed7e3bdee680532ffbb973be9dcebb8 100644 --- a/src/OpenFOAM/include/OSspecific.H +++ b/src/OpenFOAM/include/OSspecific.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -37,6 +37,7 @@ SourceFiles #define OSspecific_H #include "fileNameList.H" +#include "stringList.H" #include <sys/types.h> @@ -193,9 +194,15 @@ bool ping(const string&, const label port, const label timeOut); //- Check if machine is up by pinging port 22 (ssh) and 222 (rsh) bool ping(const string&, const label timeOut=10); -//- Execute the specified command +//- Execute the specified command via the shell. +// Uses vfork/execl internally. +// Where possible, use the list version instead. int system(const std::string& command); +//- Execute the specified command with arguments. +// Uses vfork/execvp internally +int system(const UList<string>& command); + //- Open a shared library. Return handle to library. Print error message // if library cannot be loaded (check = true) void* dlOpen(const fileName& lib, const bool check = true); diff --git a/src/postProcessing/functionObjects/systemCall/controlDict b/src/postProcessing/functionObjects/systemCall/controlDict index ff192e197cf5d83bd790654dcb71a3eb464535d3..124c5406b9b939eeaa4a2153ed6512eb845b9b0c 100644 --- a/src/postProcessing/functionObjects/systemCall/controlDict +++ b/src/postProcessing/functionObjects/systemCall/controlDict @@ -62,14 +62,15 @@ functions // called at the end of the run endCalls ( - "echo \*\*\* writing .bashrc \*\*\*" - "cat ~/.bashrc" - "echo \*\*\* done \*\*\*" + // Note: single quotes to avoid shell expansion + "echo '*** listing ~/.bashrc ***'" + "cat ~/.bashrc; echo '*** done ***'" ); - // called every ouput time + // called every output time writeCalls ( + // Note: can also backslash to escape shell meta-characters "echo \*\*\* writing data \*\*\*" ); } diff --git a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C index 6188b294681141baaa6d54e4d63da09d9afa5da9..d162635f342fae52b86acd23589b72f87530ee5a 100644 --- a/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C +++ b/src/thermophysicalModels/radiation/radiationModels/solarLoad/faceShading/faceShading.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -62,9 +62,15 @@ void Foam::faceShading::writeRays vertI++; str << "l " << vertI-1 << ' ' << vertI << nl; } - string cmd("objToVTK " + fName + " " + fName.lessExt() + ".vtk"); - Pout<< "cmd:" << cmd << endl; - system(cmd); + str.flush(); + + DynamicList<string> cmd(3); + cmd.append("objToVTK"); + cmd.append(fName); + cmd.append(fName.lessExt() + ".vtk"); + + Pout<< "cmd: objToVTK " << fName.c_str() << endl; + Foam::system(cmd); }