1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 Copyright (c) 2019-2021 The plumed team 3 (see the PEOPLE file at the root of the distribution for a list of names) 4 5 See http://www.plumed.org for more information. 6 7 This file is part of plumed, version 2. 8 9 plumed is free software: you can redistribute it and/or modify 10 it under the terms of the GNU Lesser General Public License as published by 11 the Free Software Foundation, either version 3 of the License, or 12 (at your option) any later version. 13 14 plumed is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public License 20 along with plumed. If not, see <http://www.gnu.org/licenses/>. 21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ 22 #ifndef __PLUMED_tools_Subprocess_h 23 #define __PLUMED_tools_Subprocess_h 24 25 #include "OFile.h" 26 #include "IFile.h" 27 #include <string> 28 #include <cstdio> 29 #include <memory> 30 31 namespace PLMD { 32 33 /// Small class to avoid including unistd.h here 34 class SubprocessPid; 35 36 /** 37 Class managing a subprocess. 38 39 The subprocess is launched and one can interact with it through a pipe. 40 41 In order not to consume resources, it might be possible to use this syntax: 42 43 \verbatim 44 // at construction: 45 Subprocess sp; 46 sp.stop(); 47 48 // when needed 49 { 50 auto h=sp.contStop(); 51 sp<<"command\n"; 52 sp.flush(); 53 sp.getline(answer); 54 } 55 // when h goes out of scope, subprocess is stopped again. 56 // If an exception is raised in the block, the subprocess is stopped as well. 57 \endverbatim 58 59 \warning 60 Currently `stop` and `cont` are giving problems with some MPI implementation, 61 In addition, notice that the stop signal is only sent to the child process and 62 not to the subsequently spawn processes, so it might not work as intended. 63 This feature is left here but is probably no a good idea to use it. 64 It can be enabled with `export PLUMED_ENABLE_SIGNALS=1`. 65 66 */ 67 class Subprocess { 68 /// Process ID. 69 /// We store this rather than pid_t to avoid including <unistd.h> in this header file. 70 /// This remains nullptr in the child process. 71 std::unique_ptr<SubprocessPid> pid; 72 /// File descriptor, parent to child 73 int fpc=0; 74 /// File descriptor, child to parent 75 int fcp=0; 76 /// File pointer, parent to child 77 FILE* fppc=NULL; 78 /// File pointer, child to parent 79 FILE* fpcp=NULL; 80 /// PLUMED file object, parent to child. 81 /// Used to simplify formatting 82 OFile parent_to_child; 83 /// PLUMED file object, child to parent. 84 /// Used to simplify formatting 85 IFile child_to_parent; 86 public: 87 /// Class used to cont/stop a Subprocess in an exception safe manner. 88 class Handler { 89 Subprocess* sp=nullptr; 90 /// Private constructor. 91 /// Only to be called by Subprocess::contStop() 92 explicit Handler(Subprocess* sp) noexcept; 93 friend class Subprocess; 94 public: 95 /// Default constructor 96 Handler() = default; 97 /// Destructor stops the subprocess. 98 ~Handler(); 99 /// Default copy constructor is deleted (not copyable) 100 Handler(const Handler &) = delete; 101 /// Default copy assignment is deleted (not copyable) 102 Handler & operator=(const Handler & handler) = delete; 103 /// Move constructor. 104 Handler(Handler &&) noexcept; 105 /// Move assignment. 106 Handler & operator=(Handler && handler) noexcept; 107 }; 108 /// Constructor with a command line. 109 explicit Subprocess(const std::string & cmd); 110 /// Destructor 111 ~Subprocess(); 112 /// Flush communication to process. 113 void flush(); 114 /// Check if subprocess facilities are available. 115 /// If it returns false, any call to Subprocess constructor will raise an exception. 116 static bool available() noexcept; 117 /// Get a line from the subprocess. 118 Subprocess & getline(std::string &); 119 /// Write something to the subprocess. 120 template <class T> friend Subprocess& operator<<(Subprocess& ep,const T &t); 121 /// Send a SIGCONT to the subprocess. 122 /// Better used through contStop() method. 123 void cont() noexcept; 124 /// Send a SIGSTOP to the subprocess. 125 /// Better used through contStop() method. 126 void stop() noexcept; 127 /// Returns a handler to temporarily resume the process. contStop()128 Handler contStop() noexcept { 129 return Handler(this); 130 } 131 }; 132 133 template <class T> 134 Subprocess& operator<<(Subprocess& ep,const T &t) { 135 ep.parent_to_child<<t; 136 return ep; 137 } 138 139 } 140 141 #endif 142 143