fw4spl
System.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2015.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 
8 #include "fwTools/System.hpp"
9 
10 #include <fwCore/base.hpp>
11 #ifdef ANDROID
12 #include <fwRuntime/Runtime.hpp>
13 #endif
14 
15 #include <boost/filesystem/operations.hpp>
16 #include <boost/filesystem/fstream.hpp>
17 #include <boost/regex.hpp>
18 #include <boost/lexical_cast.hpp>
19 
20 // for PID
21 #ifdef WIN32
22 #include <wtypes.h>
23 #include <windows.h>
24 #include <process.h>
25 #else
26 #include <sys/types.h>
27 #include <unistd.h>
28 #include <signal.h>
29 #endif
30 
31 
32 
33 
34 #define F4S_TMP_EXT "fw4spl-tmp"
35 
36 namespace fwTools
37 {
38 
39 std::string System::s_tempPrefix;
40 
42 {
43  typedef std::shared_ptr< RemoveTemporaryFolder > sptr;
44 
45  RemoveTemporaryFolder(const ::boost::filesystem::path &path) : m_path(path)
46  {
47  }
48 
50  {
51  ::boost::system::error_code er;
52  ::boost::filesystem::remove_all(m_path, er);
53  OSLM_ERROR_IF( "Failed to remove " << m_path << " : " << er.message(), er.value() != 0);
54  }
55  ::boost::filesystem::path m_path;
56 };
57 static RemoveTemporaryFolder::sptr autoRemoveTempFolder;
58 
59 
60 
61 static struct CleanZombies
62 {
63  CleanZombies()
64  {
66  }
67 } autoCleanZombies;
68 
69 
70 //------------------------------------------------------------------------------
71 
72 int System::getPID() noexcept
73 {
74  int pid = 0;
75 #ifdef WIN32
76  pid = _getpid();
77 #else
78  pid = getpid();
79 #endif
80 
81  return pid;
82 }
83 
84 //------------------------------------------------------------------------------
85 
86 const ::boost::filesystem::path &System::getTempPath() noexcept
87 {
88  namespace fs = ::boost::filesystem;
89  static fs::path sysTmp;
90 
91  if(!sysTmp.empty())
92  {
93  return sysTmp;
94  }
95 #ifdef ANDROID
97  if(!fs::exists(sysTmp))
98  {
99  bool res = fs::create_directories(sysTmp);
100  SLM_ASSERT(" Failed to create '"+sysTmp.string()+"' path", res);
101  }
102 #else
103 
104  ::boost::system::error_code err;
105  sysTmp = fs::temp_directory_path(err);
106 
107  if(err.value() != 0)
108  {
109 #ifdef WIN32
110  fs::path fallback("C:\\");
111 #else
112  fs::path fallback("/tmp");
113 #endif
114  OSLM_ERROR("Temporary Path Error : " << err.message() << ". " << "Falling back to " << fallback );
115  sysTmp = fallback;
116  }
117 #endif
118  return sysTmp;
119 }
120 
121 //------------------------------------------------------------------------------
122 
123 const ::boost::filesystem::path createUniqueFolder(const ::boost::filesystem::path& folderUniquePath)
124 {
125  namespace fs = ::boost::filesystem;
126  bool created = false;
127  fs::path tmpDir;
128 
129  do
130  {
131  tmpDir = fs::unique_path(folderUniquePath);
132 
133  if(!fs::exists(tmpDir))
134  {
135  fs::create_directories(tmpDir);
136 
137  created = true;
138  }
139 
140  }
141  while ( !created );
142 
143  return tmpDir;
144 }
145 
146 //------------------------------------------------------------------------------
147 
148 const ::boost::filesystem::path System::getTemporaryFolder(const std::string& subFolderPrefix) noexcept
149 {
150  namespace fs = ::boost::filesystem;
151  static fs::path tmpDirPath;
152 
153  if(!tmpDirPath.empty() && fs::exists(tmpDirPath))
154  {
155  if(!subFolderPrefix.empty())
156  {
157  const std::string subDirName = subFolderPrefix + "-" + "%%%%%%%%%%%%";
158  fs::path tmpSubDir = createUniqueFolder(tmpDirPath/subDirName);
159  return tmpSubDir;
160  }
161 
162  return tmpDirPath;
163  }
164 
165  const fs::path &sysTmp = getTempPath();
166 
167  const std::string tmpDirName = s_tempPrefix + (s_tempPrefix.empty() ? "" : "-") + "%%%%%%%%%%%%." F4S_TMP_EXT;
168  fs::path tmpDir = createUniqueFolder(sysTmp/tmpDirName);
169  tmpDirPath = tmpDir; // tmpDirPath always set to root tmp dir
170 
171  fs::path pidFile = tmpDir / (::boost::lexical_cast<std::string>(getPID()) + ".pid");
172  fs::fstream( pidFile, std::ios::out ).close();
173 
174  autoRemoveTempFolder = std::make_shared<RemoveTemporaryFolder>(tmpDirPath);
175 
176  if(!subFolderPrefix.empty())
177  {
178  const std::string subDirName = subFolderPrefix + "-" + "%%%%%%%%%%%%";
179  tmpDir = createUniqueFolder(tmpDir/subDirName);
180  }
181 
182  OSLM_INFO("Temporary folder is : " << tmpDirPath);
183  return tmpDir;
184 }
185 
186 //------------------------------------------------------------------------------
187 
188 bool System::isProcessRunning(int pid) noexcept
189 {
190 #ifdef WIN32
191  HANDLE hProcess = OpenProcess(SYNCHRONIZE, FALSE, pid);
192  if (!hProcess)
193  {
194  return false;
195  }
196  else
197  {
198  CloseHandle(hProcess);
199  return true;
200  }
201 #else
202  return kill(pid,0) == 0;
203 #endif
204 
205  return true;
206 }
207 
208 //------------------------------------------------------------------------------
209 
210 int System::tempFolderPID(const ::boost::filesystem::path &dir) noexcept
211 {
212  namespace fs = ::boost::filesystem;
213 
214  const ::boost::regex pidFilter( "([[:digit:]]+)\\.pid" );
215 
216  fs::directory_iterator i( dir );
217  fs::directory_iterator endIter;
218 
219  int pid = 0;
220 
221  for(; i != endIter; ++i )
222  {
223  // Skip if not a dir
224  if( !fs::is_regular_file( i->status() ) )
225  {
226  continue;
227  }
228 
229  ::boost::smatch what;
230 
231  // Skip if no match
232  std::string s = i->path().filename().string();
233  if( !::boost::regex_match( s, what, pidFilter ) )
234  {
235  continue;
236  }
237 
238  try
239  {
240  pid = ::boost::lexical_cast< int >(what.str(1));
241  break;
242  }
243  catch (boost::bad_lexical_cast&)
244  {
245  }
246 
247  }
248  return pid;
249 }
250 
251 //------------------------------------------------------------------------------
252 
253 void System::cleanZombies(const ::boost::filesystem::path &dir) noexcept
254 {
255  namespace fs = ::boost::filesystem;
256 
257  const ::boost::regex tmpFolderFilter( ".*\\." F4S_TMP_EXT );
258 
259  std::vector< fs::path > allTempFolders;
260 
261  fs::directory_iterator i( dir );
262  fs::directory_iterator endIter;
263 
264  for(; i != endIter; ++i )
265  {
266  // Skip if not a dir
267  if( !fs::is_directory( i->status() ) )
268  {
269  continue;
270  }
271 
272  ::boost::smatch what;
273 
274  // Skip if no match
275  if( !::boost::regex_match( i->path().filename().string(), what, tmpFolderFilter ) )
276  {
277  continue;
278  }
279 
280  allTempFolders.push_back( i->path() );
281  }
282 
283 
284  for( const fs::path &foundTmpDir : allTempFolders)
285  {
286  int pid = tempFolderPID(foundTmpDir);
287 
288  if(pid && !isProcessRunning(pid))
289  {
290  OSLM_INFO("Removing old temp dir : " << foundTmpDir);
291 
292  ::boost::system::error_code er;
293  fs::remove_all(foundTmpDir, er);
294 
295  OSLM_INFO_IF( "Failed to remove " << foundTmpDir << " : " << er.message(), er.value() != 0);
296  }
297  }
298 
299 
300 }
301 
302 //------------------------------------------------------------------------------
303 
304 } //end namespace fwTools
static FWTOOLS_API void cleanZombies(const ::boost::filesystem::path &dir) noexcept
Clean the zombie folders of old processes in given directory.
Definition: System.cpp:253
static FWRUNTIME_API Runtime * getDefault()
Retrieves the default runtime instance.
Definition: Runtime.cpp:286
The namespace fwTools contains several tools like UUID, factory, dispatche, stringizer, macros, helper.
static FWTOOLS_API int tempFolderPID(const ::boost::filesystem::path &dir) noexcept
Returns the pid of a temporary folder If the given folder contains a file matching *...
Definition: System.cpp:210
#define OSLM_INFO_IF(message, cond)
Definition: spyLog.hpp:256
#define OSLM_INFO(message)
Definition: spyLog.hpp:252
#define OSLM_ERROR(message)
Definition: spyLog.hpp:274
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
static FWTOOLS_API int getPID() noexcept
Returns the pid of the current process.
Definition: System.cpp:72
static FWTOOLS_APIconst::boost::filesystem::path getTemporaryFolder(const std::string &subFolderPrefix="") noexcept
Returns a unique per-process temporary folder. The top level temporary folder will be automatically d...
Definition: System.cpp:148
static FWTOOLS_API bool isProcessRunning(int pid) noexcept
Test if process is Active.
Definition: System.cpp:188
static FWTOOLS_APIconst::boost::filesystem::path & getTempPath() noexcept
Returns the system&#39;s temporary folder. Returns the value returned by boost::filesystem::temp_director...
Definition: System.cpp:86
#define OSLM_ERROR_IF(message, cond)
Definition: spyLog.hpp:278
FWRUNTIME_API::boost::filesystem::path getWorkingPath() const
Get the path where Bundles and share folder are located.
Definition: Runtime.cpp:402