From 07ec741e2acd23c70310a763ffee4aedac8e2ad4 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Wed, 3 Apr 2019 19:00:06 +0200 Subject: [PATCH] ENH: add OSspecific/MSwindows (#1238) --- src/OSspecific/MSwindows/Allwmake | 12 + src/OSspecific/MSwindows/MSwindows.C | 1288 +++++++++++++++++ src/OSspecific/MSwindows/MSwindows.H | 69 + src/OSspecific/MSwindows/Make/files | 21 + src/OSspecific/MSwindows/Make/options | 1 + src/OSspecific/MSwindows/cpuInfo/cpuInfo.C | 68 + src/OSspecific/MSwindows/cpuInfo/cpuInfo.H | 111 ++ src/OSspecific/MSwindows/cpuTime/cpuTime.H | 40 + src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H | 48 + .../MSwindows/fileMonitor/fileMonitor.C | 625 ++++++++ .../MSwindows/fileMonitor/fileMonitor.H | 165 +++ src/OSspecific/MSwindows/fileStat/fileStat.C | 214 +++ src/OSspecific/MSwindows/fileStat/fileStat.H | 180 +++ src/OSspecific/MSwindows/memInfo/memInfo.C | 109 ++ src/OSspecific/MSwindows/memInfo/memInfo.H | 151 ++ .../MSwindows/printStack/dummyPrintStack.C | 40 + src/OSspecific/MSwindows/regExp/regExp.H | 40 + src/OSspecific/MSwindows/regExp/regExpFwd.H | 48 + src/OSspecific/MSwindows/signals/sigFpe.C | 235 +++ src/OSspecific/MSwindows/signals/sigFpe.H | 186 +++ src/OSspecific/MSwindows/signals/sigInt.C | 96 ++ src/OSspecific/MSwindows/signals/sigInt.H | 102 ++ src/OSspecific/MSwindows/signals/sigQuit.C | 99 ++ src/OSspecific/MSwindows/signals/sigQuit.H | 102 ++ src/OSspecific/MSwindows/signals/sigSegv.C | 96 ++ src/OSspecific/MSwindows/signals/sigSegv.H | 102 ++ .../MSwindows/signals/sigStopAtWriteNow.C | 174 +++ .../MSwindows/signals/sigStopAtWriteNow.H | 107 ++ .../MSwindows/signals/sigWriteNow.C | 154 ++ .../MSwindows/signals/sigWriteNow.H | 108 ++ .../MSwindows/signals/signalMacros.C | 77 + src/OSspecific/MSwindows/signals/timer.C | 156 ++ src/OSspecific/MSwindows/signals/timer.H | 130 ++ 33 files changed, 5154 insertions(+) create mode 100755 src/OSspecific/MSwindows/Allwmake create mode 100644 src/OSspecific/MSwindows/MSwindows.C create mode 100644 src/OSspecific/MSwindows/MSwindows.H create mode 100644 src/OSspecific/MSwindows/Make/files create mode 100644 src/OSspecific/MSwindows/Make/options create mode 100644 src/OSspecific/MSwindows/cpuInfo/cpuInfo.C create mode 100644 src/OSspecific/MSwindows/cpuInfo/cpuInfo.H create mode 100644 src/OSspecific/MSwindows/cpuTime/cpuTime.H create mode 100644 src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H create mode 100644 src/OSspecific/MSwindows/fileMonitor/fileMonitor.C create mode 100644 src/OSspecific/MSwindows/fileMonitor/fileMonitor.H create mode 100644 src/OSspecific/MSwindows/fileStat/fileStat.C create mode 100644 src/OSspecific/MSwindows/fileStat/fileStat.H create mode 100644 src/OSspecific/MSwindows/memInfo/memInfo.C create mode 100644 src/OSspecific/MSwindows/memInfo/memInfo.H create mode 100644 src/OSspecific/MSwindows/printStack/dummyPrintStack.C create mode 100644 src/OSspecific/MSwindows/regExp/regExp.H create mode 100644 src/OSspecific/MSwindows/regExp/regExpFwd.H create mode 100644 src/OSspecific/MSwindows/signals/sigFpe.C create mode 100644 src/OSspecific/MSwindows/signals/sigFpe.H create mode 100644 src/OSspecific/MSwindows/signals/sigInt.C create mode 100644 src/OSspecific/MSwindows/signals/sigInt.H create mode 100644 src/OSspecific/MSwindows/signals/sigQuit.C create mode 100644 src/OSspecific/MSwindows/signals/sigQuit.H create mode 100644 src/OSspecific/MSwindows/signals/sigSegv.C create mode 100644 src/OSspecific/MSwindows/signals/sigSegv.H create mode 100644 src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C create mode 100644 src/OSspecific/MSwindows/signals/sigStopAtWriteNow.H create mode 100644 src/OSspecific/MSwindows/signals/sigWriteNow.C create mode 100644 src/OSspecific/MSwindows/signals/sigWriteNow.H create mode 100644 src/OSspecific/MSwindows/signals/signalMacros.C create mode 100644 src/OSspecific/MSwindows/signals/timer.C create mode 100644 src/OSspecific/MSwindows/signals/timer.H diff --git a/src/OSspecific/MSwindows/Allwmake b/src/OSspecific/MSwindows/Allwmake new file mode 100755 index 00000000000..24fb418826f --- /dev/null +++ b/src/OSspecific/MSwindows/Allwmake @@ -0,0 +1,12 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +targetType=libo # Preferred library type +. $WM_PROJECT_DIR/wmake/scripts/AllwmakeParseArguments $* + +#------------------------------------------------------------------------------ +unset COMP_FLAGS LINK_FLAGS + +# Make object (non-shared by default) +wmake $targetType + +#------------------------------------------------------------------------------ diff --git a/src/OSspecific/MSwindows/MSwindows.C b/src/OSspecific/MSwindows/MSwindows.C new file mode 100644 index 00000000000..30fb55792f4 --- /dev/null +++ b/src/OSspecific/MSwindows/MSwindows.C @@ -0,0 +1,1288 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2017 OpenFOAM Foundation + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "OSspecific.H" +#include "MSwindows.H" +#include "fileName.H" +#include "fileStat.H" +#include "DynamicList.H" +#include "CStringList.H" +#include "IOstreams.H" +#include "Pstream.H" +#undef DebugInfo // Windows name clash with OpenFOAM messageStream + +#include <cassert> +#include <cstdlib> +#include <fstream> +#include <unordered_map> + +// Windows headers +#define WIN32_LEAN_AND_MEAN +#include <csignal> +#include <io.h> // For _close +#include <windows.h> + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(MSwindows, 0); +} + + +namespace Foam +{ + // Don't abort under windows, causes abort dialog to popup. + // Instead just exit with exitCode. + static void sigAbortHandler(int exitCode) + { + ::exit(exitCode); + } + + static bool installAbortHandler() + { + // If it didn't succeed there's not much we can do, + // so don't check result. + ::signal(SIGABRT, &sigAbortHandler); + return true; + } + + static bool const abortHandlerInstalled = installAbortHandler(); + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace MSwindows +{ + +//- A simple directory contents iterator +class directoryIterator +{ + HANDLE handle_; + + bool exists_; + + bool hidden_; + + std::string item_; + + //- Accept file/dir name + inline bool accept() const + { + return + ( + item_.size() && item_ != "." && item_ != ".." + && (hidden_ || item_[0] != '.') + ); + } + + +public: + + //- Construct for dirName, optionally allowing hidden files/dirs + directoryIterator(const fileName& dirName, bool allowHidden = false) + : + handle_(INVALID_HANDLE_VALUE), + exists_(false), + hidden_(allowHidden), + item_() + { + if (!dirName.empty()) + { + WIN32_FIND_DATA findData; + + handle_ = ::FindFirstFile((dirName/"*").c_str(), &findData); + + if (good()) + { + exists_ = true; + item_ = findData.cFileName; + + // If first element is not acceptable, get another one + if (!accept()) + { + next(); + } + } + } + } + + + //- Destructor + ~directoryIterator() + { + close(); + } + + + // Member Functions + + //- Directory existed for opening + bool exists() const + { + return exists_; + } + + //- Directory pointer is valid + bool good() const + { + return (INVALID_HANDLE_VALUE != handle_); + } + + //- Close directory + void close() + { + if (good()) + { + ::FindClose(handle_); + handle_ = INVALID_HANDLE_VALUE; + } + } + + //- The current item + const std::string& val() const + { + return item_; + } + + //- Read next item, always ignoring "." and ".." entries. + // Normally also ignore hidden files/dirs (beginning with '.') + // Automatically close when it runs out of items + bool next() + { + if (good()) + { + WIN32_FIND_DATA findData; + + while (::FindNextFile(handle_, &findData)) + { + item_ = findData.cFileName; + + if (accept()) + { + return true; + } + } + close(); // No more items + } + + return false; + } + + + // Member Operators + + //- Same as good() + operator bool() const + { + return good(); + } + + //- Same as val() + const std::string& operator*() const + { + return val(); + } + + //- Same as next() + directoryIterator& operator++() + { + next(); + return *this; + } +}; + +} // End namespace MSwindows +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +std::string Foam::MSwindows::lastError() +{ + // Retrieve the system error message for the last-error code + + // Based on an example at: + // http://msdn2.microsoft.com/en-us/library/ms680582(VS.85).aspx + + LPVOID lpMsgBuf; + DWORD dw = GetLastError(); + + FormatMessage + ( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, // source + dw, // message-id + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // language-id + reinterpret_cast<LPTSTR>(&lpMsgBuf), + 0, NULL + ); + + const char* fmt = "Error %d: %s"; + + // Use snprintf with zero to establish the size (without '\0') required + std::string output; + + int n = ::snprintf(nullptr, 0, fmt, static_cast<LPCTSTR>(lpMsgBuf)); + + if (n > 0) + { + output.resize(n+1); + + // Print directly into buffer + n = ::snprintf(&(output[0]), n+1, fmt, static_cast<LPCTSTR>(lpMsgBuf)); + output.resize(n); + } + + LocalFree(lpMsgBuf); + + return output; +} + + +std::string Foam::MSwindows::userName() +{ + const DWORD bufLen = 256; + TCHAR buf[bufLen]; + DWORD len = bufLen; + + if (::GetUserName(buf, &len)) + { + return buf; + } + + std::string str; + + if + ( + ERROR_INSUFFICIENT_BUFFER == ::GetLastError() + && len < 2048 + ) + { + // The len is with trailing '\0' + str.resize(len); + + // Retrieve directly into buffer + ::GetUserName(&(str[0]), &len); + + // Without trailing '\0' + str.resize(len-1); + } + + return str; +} + + +pid_t Foam::pid() +{ + const DWORD processId = ::GetCurrentProcessId(); + return processId; +} + + +pid_t Foam::ppid() +{ + // No equivalent under windows. + + if (MSwindows::debug) + { + Info<< "ppid not supported under MSwindows" << endl; + } + + return 0; +} + + +pid_t Foam::pgid() +{ + // No equivalent under windows. + + if (MSwindows::debug) + { + Info<< "pgid not supported under MSwindows" << endl; + } + + return 0; +} + + +bool Foam::env(const std::string& envName) +{ + // An empty envName => always false + return !envName.empty() && + ::GetEnvironmentVariable(envName.c_str(), nullptr, 0); +} + + +Foam::string Foam::getEnv(const std::string& envName) +{ + std::string env; + + const auto len = ::GetEnvironmentVariable(envName.c_str(), nullptr, 0); + + if (len) + { + env.resize(len+1); + ::GetEnvironmentVariable(envName.c_str(), &(env[0]), len+1); + + env.resize(len); + return fileName::validate(env); + } + + return env; +} + + +bool Foam::setEnv +( + const word& envName, + const std::string& value, + const bool overwrite +) +{ + // Ignore an empty envName => always false + return + ( + !envName.empty() + && ::SetEnvironmentVariable(envName.c_str(), value.c_str()) + ); +} + + +Foam::string Foam::hostName(bool) +{ + const DWORD bufLen = MAX_COMPUTERNAME_LENGTH + 1; + TCHAR buf[bufLen]; + DWORD len = bufLen; + + return ::GetComputerName(buf, &len) ? buf : string(); +} + + +Foam::string Foam::domainName() +{ + // Could use ::gethostname and ::gethostbyname like POSIX.C, but would + // then need to link against ws_32. Prefer to minimize dependencies. + + return string::null; +} + + +Foam::string Foam::userName() +{ + string name = Foam::getEnv("USERNAME"); + + if (name.empty()) + { + name = MSwindows::userName(); + } + + return name; +} + + +bool Foam::isAdministrator() +{ + // Assume worst case + return true; +} + + +Foam::fileName Foam::home() +{ + fileName env = Foam::getEnv("HOME"); + + if (env.empty()) + { + env = Foam::getEnv("USERPROFILE"); + } + + return env; +} + + +Foam::fileName Foam::home(const std::string& userName) +{ + return Foam::home(); +} + + +Foam::fileName Foam::cwd() +{ + string path; + const DWORD len = ::GetCurrentDirectory(0, nullptr); + + if (len) + { + path.resize(len+1); + + ::GetCurrentDirectory(len+1, &(path[0])); + + path.resize(len); + + return fileName::validate(path); + } + + FatalErrorInFunction + << "Couldn't get the current working directory" + << exit(FatalError); + + return fileName(); +} + + +Foam::fileName Foam::cwd(bool logical) +{ + return Foam::cwd(); +} + + +bool Foam::chDir(const fileName& dir) +{ + // Ignore an empty dir name => always false + return !dir.empty() && ::SetCurrentDirectory(dir.c_str());; +} + + +bool Foam::mkDir(const fileName& pathName, const mode_t mode) +{ + // empty names are meaningless + if (pathName.empty()) + { + return false; + } + + bool ok = ::CreateDirectory(pathName.c_str(), NULL); + + if (ok) + { + Foam::chMod(pathName, mode); + return true; + } + + const DWORD error = ::GetLastError(); + switch (error) + { + case ERROR_ALREADY_EXISTS: + { + ok = true; + break; + } + + case ERROR_PATH_NOT_FOUND: + { + // Part of the path does not exist so try to create it + const fileName& parentName = pathName.path(); + + if (parentName.size() && mkDir(parentName, mode)) + { + ok = mkDir(pathName, mode); + } + break; + } + } + + if (!ok) + { + FatalErrorInFunction + << "Couldn't create directory: " << pathName + << " " << MSwindows::lastError() + << exit(FatalError); + } + + return ok; +} + + +bool Foam::chMod(const fileName& name, const mode_t m) +{ + // Ignore an empty name => always false + return !name.empty() && _chmod(name.c_str(), m) == 0; +} + + +mode_t Foam::mode(const fileName& name, const bool followLink) +{ + // Ignore an empty name => always 0 + if (!name.empty()) + { + fileStat fileStatus(name, followLink); + if (fileStatus.valid()) + { + return fileStatus.status().st_mode; + } + } + + return 0; +} + + +// Windows equivalent to S_ISDIR +#define ms_isdir(a) \ + ((m != INVALID_FILE_ATTRIBUTES) && (m & FILE_ATTRIBUTE_DIRECTORY)) + +// Windows equivalent to S_ISREG +#define ms_isreg(s) \ + ((m != INVALID_FILE_ATTRIBUTES) && !(m & FILE_ATTRIBUTE_DIRECTORY)) + + +Foam::fileName::Type Foam::type +( + const fileName& name, + const bool /* followLink */ +) +{ + // Ignore an empty name => always UNDEFINED + if (name.empty()) + { + return fileName::UNDEFINED; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + if (ms_isreg(m)) + { + return fileName::FILE; + } + else if (ms_isdir(m)) + { + return fileName::DIRECTORY; + } + + return fileName::UNDEFINED; +} + + +// Local check for gz file +static bool isGzFile(const std::string& name) +{ + const DWORD m = ::GetFileAttributes((name + ".gz").c_str()); + return ms_isreg(m); +} + + +bool Foam::exists +( + const fileName& name, + const bool checkGzip, + const bool followLink +) +{ + // Ignore an empty name => always false + if (name.empty()) + { + return false; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + return (ms_isdir(m) || ms_isreg(m) || (checkGzip && isGzFile(name))); +} + + +bool Foam::isDir(const fileName& name, const bool followLink) +{ + // Ignore an empty name => always false + if (name.empty()) + { + return false; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + return ms_isdir(m); +} + + +bool Foam::isFile +( + const fileName& name, + const bool checkGzip, + const bool followLink +) +{ + // Ignore an empty name => always false + if (name.empty()) + { + return false; + } + + const DWORD m = ::GetFileAttributes(name.c_str()); + + return (ms_isreg(m) || (!ms_isdir(m) && checkGzip && isGzFile(name))); +} + + +off_t Foam::fileSize(const fileName& name, const bool followLink) +{ + // Ignore an empty name + if (!name.empty()) + { + fileStat fileStatus(name, followLink); + if (fileStatus.valid()) + { + return fileStatus.status().st_size; + } + } + + return -1; +} + + +time_t Foam::lastModified(const fileName& name, const bool followLink) +{ + // Ignore an empty name + return name.empty() ? 0 : fileStat(name, followLink).modTime(); +} + + +double Foam::highResLastModified(const fileName& name, const bool followLink) +{ + // Ignore an empty name + return name.empty() ? 0 : fileStat(name, followLink).dmodTime(); +} + + +Foam::fileNameList Foam::readDir +( + const fileName& directory, + const fileName::Type type, + const bool filtergz, + const bool followLink +) +{ + // Initial filename list size + // also used as increment if initial size found to be insufficient + static constexpr int maxNnames = 100; + + // Basic sanity: cannot strip '.gz' from directory names + const bool stripgz = filtergz && (type != fileName::DIRECTORY); + const word extgz("gz"); + + fileNameList dirEntries; + + // Iterate contents (ignores an empty directory name) + + MSwindows::directoryIterator dirIter(directory); + + if (!dirIter.exists()) + { + if (MSwindows::debug) + { + InfoInFunction + << "cannot open directory " << directory << endl; + } + + return dirEntries; + } + + if (MSwindows::debug) + { + InfoInFunction + << " : reading directory " << directory << endl; + } + + label nFailed = 0; // Entries with invalid characters + label nEntries = 0; // Number of selected entries + dirEntries.resize(maxNnames); + + // Process all the directory entries + for (/*nil*/; dirIter; ++dirIter) + { + const std::string& item = *dirIter; + + // Validate filename without quotes, etc in the name. + // No duplicate slashes to strip - dirent will not have them anyhow. + + const fileName name(fileName::validate(item)); + if (name != item) + { + ++nFailed; + } + else if + ( + (type == fileName::DIRECTORY) + || (type == fileName::FILE && !fileName::isBackup(name)) + ) + { + if ((directory/name).type() == type) + { + if (nEntries >= dirEntries.size()) + { + dirEntries.resize(dirEntries.size() + maxNnames); + } + + if (stripgz && name.hasExt(extgz)) + { + dirEntries[nEntries++] = name.lessExt(); + } + else + { + dirEntries[nEntries++] = name; + } + } + } + } + + // Finalize the length of the entries list + dirEntries.resize(nEntries); + + if (nFailed && MSwindows::debug) + { + std::cerr + << "Foam::readDir() : reading directory " << directory << nl + << nFailed << " entries with invalid characters in their name" + << std::endl; + } + + return dirEntries; +} + + +bool Foam::cp(const fileName& src, const fileName& dest, const bool followLink) +{ + // Make sure source exists - this also handles an empty source name + if (!exists(src)) + { + return false; + } + + fileName destFile(dest); + + const fileName::Type srcType = src.type(followLink); + + // Check type of source file. + if (srcType == fileName::FILE) + { + // If dest is a directory, create the destination file name. + if (destFile.type() == fileName::DIRECTORY) + { + destFile = destFile/src.name(); + } + + // Make sure the destination directory exists. + if (!isDir(destFile.path()) && !mkDir(destFile.path())) + { + return false; + } + + // Open and check streams. + // - use binary mode to avoid any issues + std::ifstream srcStream(src, ios_base::in | ios_base::binary); + if (!srcStream) + { + return false; + } + + // - use binary mode to avoid any issues + std::ofstream destStream(destFile, ios_base::out | ios_base::binary); + if (!destStream) + { + return false; + } + + // Copy character data. + char ch; + while (srcStream.get(ch)) + { + destStream.put(ch); + } + + // Final check. + if (!srcStream.eof() || !destStream) + { + return false; + } + } + else if (srcType == fileName::DIRECTORY) + { + // If dest is a directory, create the destination file name. + if (destFile.type() == fileName::DIRECTORY) + { + destFile /= src.components().last(); + } + + // Make sure the destination directory extists. + if (!isDir(destFile) && !mkDir(destFile)) + { + return false; + } + + // Copy files + fileNameList files = readDir(src, fileName::FILE, false, followLink); + for (const fileName& item : files) + { + if (MSwindows::debug) + { + Info<< "Copying : " << src/item + << " to " << destFile/item << endl; + } + + // File to file. + Foam::cp(src/item, destFile/item); + } + + // Copy sub directories. + fileNameList dirs = readDir + ( + src, + fileName::DIRECTORY, + false, + followLink + ); + + for (const fileName& item : dirs) + { + if (MSwindows::debug) + { + Info<< "Copying : " << src/item + << " to " << destFile << endl; + } + + // Dir to Dir. + Foam::cp(src/item, destFile); + } + } + else + { + return false; + } + + return true; +} + + +bool Foam::ln(const fileName& src, const fileName& dst) +{ + // links are poorly supported, or need adminstrator privileges. + // Skip for now. + + if (MSwindows::debug) + { + Info<< "MSwindows does not support ln - softlinking" << endl; + } + + return false; +} + + +bool Foam::mv(const fileName& src, const fileName& dst, const bool followLink) +{ + if (MSwindows::debug) + { + Info<< "Move : " << src << " to " << dst << endl; + } + + // Ignore an empty names => always false + if (src.empty() || dst.empty()) + { + return false; + } + + + if + ( + dst.type() == fileName::DIRECTORY + && src.type(followLink) != fileName::DIRECTORY + ) + { + const fileName dstName(dst/src.name()); + + return 0 == std::rename(src.c_str(), dstName.c_str()); + } + + return 0 == std::rename(src.c_str(), dst.c_str()); +} + + +bool Foam::mvBak(const fileName& src, const std::string& ext) +{ + // Ignore an empty name or extension => always false + if (src.empty() || ext.empty()) + { + return false; + } + + if (exists(src, false)) + { + const int maxIndex = 99; + char index[3]; + + for (int n = 0; n <= maxIndex; n++) + { + fileName dstName(src + "." + ext); + if (n) + { + sprintf(index, "%02d", n); + dstName += index; + } + + // avoid overwriting existing files, except for the last + // possible index where we have no choice + if (!exists(dstName, false) || n == maxIndex) + { + return (0 == std::rename(src.c_str(), dstName.c_str())); + } + } + } + + // fall-through: nothing to do + return false; +} + + +bool Foam::rm(const fileName& file) +{ + if (MSwindows::debug) + { + Info<< "Removing : " << file << endl; + } + + // Ignore an empty name => always false + if (file.empty()) + { + return false; + } + + + // If removal of plain file name failed, try with .gz + + return + ( + 0 == std::remove(file.c_str()) + || 0 == std::remove((file + ".gz").c_str()) + ); +} + + +bool Foam::rmDir(const fileName& directory, const bool silent) +{ + // Iterate contents (ignores an empty directory name) + // Also retain hidden files/dirs for removal + + MSwindows::directoryIterator dirIter(directory, true); + + if (!dirIter.exists()) + { + if (!silent) + { + WarningInFunction + << "cannot open directory " << directory << endl; + } + } + + if (MSwindows::debug) + { + InfoInFunction + << " : removing directory " << directory << endl; + } + + + // Process each directory entry, counting any errors encountered + label nErrors = 0; + + for (/*nil*/; dirIter; ++dirIter) + { + const std::string& item = *dirIter; + + // Allow invalid characters (spaces, quotes, etc), + // otherwise we cannot remove subdirs with these types of names. + // -> const fileName path = directory/name; <- + + const fileName path(fileName::concat(directory, item)); + + if (path.type(false) == fileName::DIRECTORY) + { + if (!rmDir(path, true)) // Only report errors at the top-level + { + ++nErrors; + } + } + else + { + if (!rm(path)) + { + ++nErrors; + } + } + } + + if (nErrors) + { + if (!silent) + { + WarningInFunction + << "failed to remove directory " << directory << nl + << "could not remove " << nErrors << " sub-entries" << endl; + } + } + else + { + if (!::RemoveDirectory(directory.c_str())) + { + ++nErrors; + if (!silent) + { + WarningInFunction + << "failed to remove directory " << directory << endl; + } + } + } + + return !nErrors; +} + + +unsigned int Foam::sleep(const unsigned int sec) +{ + ::Sleep(1000*sec); // in milliseconds + + return 0; +} + + +void Foam::fdClose(const int fd) +{ + if (::_close(fd) != 0) + { + FatalErrorInFunction + << "close error on " << fd << endl + << abort(FatalError); + } +} + + +bool Foam::ping +( + const std::string& destName, + const label destPort, + const label timeOut +) +{ + // Appears that socket calls require adminstrator privileges. + // Skip for now. + + if (MSwindows::debug) + { + Info<< "MSwindows does not support ping" << endl; + } + + return false; +} + + +bool Foam::ping(const std::string& host, const label timeOut) +{ + return ping(host, 222, timeOut) || ping(host, 22, timeOut); +} + + +int Foam::system(const std::string& command, const bool bg) +{ + if (MSwindows::debug && bg) + { + InfoInFunction + << "MSwindows does not support background (fork) tasks" << endl; + } + + return std::system(command.c_str()); +} + + +int Foam::system(const CStringList& command, const bool bg) +{ + if (command.empty()) + { + // 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; + } + + const int count = command.size(); + + std::string cmd; + + for (int i = 0; i < count; ++i) + { + if (i) cmd += ' '; + cmd += command[i]; + } + + return system(cmd, bg); +} + + +int Foam::system(const UList<Foam::string>& command, const bool bg) +{ + if (command.empty()) + { + // Treat an empty command as a successful no-op. + return 0; + } + + const int count = command.size(); + + std::string cmd; + + for (int i = 0; i < count; ++i) + { + if (i) cmd += ' '; + cmd += command[i]; + } + + return system(cmd, bg); +} + + +// Explicitly track loaded libraries, rather than use +// EnumerateLoadedModules64 and have to link against +// Dbghelp.dll +// Details at http://msdn.microsoft.com/en-us/library/ms679316(v=vs.85).aspx + +static std::unordered_map<void*, std::string> libsLoaded; + + +void* Foam::dlOpen(const fileName& libName, const bool check) +{ + if (MSwindows::debug) + { + std::cout + << "dlOpen(const fileName&)" + << " : dlopen of " << libName << std::endl; + } + + // Map "libXX.so" and "libXX" to "libXX.dll" + + fileName winLibName(libName.lessExt().ext("dll")); + void* handle = ::LoadLibrary(winLibName.c_str()); + + if (handle) + { + libsLoaded[handle] = libName.lessExt(); + } + else if (check) + { + WarningInFunction + << "dlopen error : " << MSwindows::lastError() + << endl; + } + + if (MSwindows::debug) + { + std::cout + << "dlOpen(const fileName&)" + << " : dlopen of " << libName + << " handle " << handle << std::endl; + } + + return handle; +} + + +bool Foam::dlClose(void* const handle) +{ + if (MSwindows::debug) + { + std::cout + << "dlClose(void*)" + << " : dlclose of handle " << handle << std::endl; + } + + const bool ok = ::FreeLibrary(static_cast<HMODULE>(handle)); + + if (ok) + { + libsLoaded.erase(handle); + } + + return ok; +} + + +void* Foam::dlSymFind(void* handle, const std::string& symbol, bool required) +{ + if (!required && (!handle || symbol.empty())) + { + return nullptr; + } + + if (MSwindows::debug) + { + std::cout + << "dlSymFind(void*, const std::string&, bool)" + << " : dlsym of " << symbol << std::endl; + } + + // Get address of symbol, or nullptr on failure + void* fun = + reinterpret_cast<void *> + ( + ::GetProcAddress(static_cast<HMODULE>(handle), symbol.c_str()) + ); + + // Any error? + if (!fun && required) + { + WarningInFunction + << "Cannot lookup symbol " << symbol << " : " + << MSwindows::lastError() << endl; + } + + return fun; +} + + +Foam::fileNameList Foam::dlLoaded() +{ + DynamicList<fileName> libs(libsLoaded.size()); + + for (const auto& item : libsLoaded) + { + libs.append(item.second); + } + + if (MSwindows::debug) + { + std::cout + << "dlLoaded()" + << " : determined loaded libraries :" << libs.size() << std::endl; + } + + return libs; +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/MSwindows.H b/src/OSspecific/MSwindows/MSwindows.H new file mode 100644 index 00000000000..e0f7c317b2e --- /dev/null +++ b/src/OSspecific/MSwindows/MSwindows.H @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Namespace + Foam::MSwindows + +Description + OS-specific functions implemented for MS-windows. + +SourceFiles + MSwindows.C + +\*---------------------------------------------------------------------------*/ + +#ifndef MSwindows_H +#define MSwindows_H + +#include "className.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace MSwindows +{ + //- Declare namespace and its debug switch + NamespaceName("MSwindows"); + + //- The last Windows API error from GetLastError + std::string lastError(); + + //- The user-name from Windows API GetUserName + std::string userName(); +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/Make/files b/src/OSspecific/MSwindows/Make/files new file mode 100644 index 00000000000..964f34106e0 --- /dev/null +++ b/src/OSspecific/MSwindows/Make/files @@ -0,0 +1,21 @@ +MSwindows.C + +cpuInfo/cpuInfo.C +memInfo/memInfo.C + +signals/sigFpe.C +signals/sigInt.C +signals/sigQuit.C +signals/sigSegv.C +signals/sigStopAtWriteNow.C +signals/sigWriteNow.C +signals/timer.C + +fileStat/fileStat.C + +/* Without inotify */ +fileMonitor/fileMonitor.C + +printStack/dummyPrintStack.C + +LIB = $(FOAM_LIBBIN)/libOSspecific diff --git a/src/OSspecific/MSwindows/Make/options b/src/OSspecific/MSwindows/Make/options new file mode 100644 index 00000000000..3f86d412a62 --- /dev/null +++ b/src/OSspecific/MSwindows/Make/options @@ -0,0 +1 @@ +EXE_INC = $(COMP_FLAGS) diff --git a/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C new file mode 100644 index 00000000000..d20330b78e4 --- /dev/null +++ b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.C @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "cpuInfo.H" +#include "IOstreams.H" + +#include <thread> + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::cpuInfo::cpuInfo() +: + vendor_id(), + model_name(), + cpu_family(-1), + model(-1), + cpu_MHz(0), + siblings(0), + cpu_cores(std::thread::hardware_concurrency()) +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::cpuInfo::write(Ostream& os) const +{ + if (!vendor_id.empty()) + { + os.writeEntry("vendor_id", vendor_id); + } + if (!model_name.empty()) + { + os.writeEntry("model_name", model_name); + } + + os.writeEntryIfDifferent<int>("cpu_family", -1, cpu_family); + os.writeEntryIfDifferent<int>("model", -1, model); + os.writeEntryIfDifferent<float>("cpu_MHz", 0, cpu_MHz); + os.writeEntryIfDifferent<int>("cpu_cores", 0, cpu_cores); + os.writeEntryIfDifferent<int>("siblings", 0, siblings); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H new file mode 100644 index 00000000000..1dbba0b6ee5 --- /dev/null +++ b/src/OSspecific/MSwindows/cpuInfo/cpuInfo.H @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::cpuInfo + +Description + General CPU characteristics. + + If the machine has multiple cpus/cores, only the characteristics + of the first core are used. + +Note + Windows variant only provides the number of cores. + +SourceFiles + cpuInfo.C + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuInfo_H +#define cpuInfo_H + +#include <string> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declarations +class Ostream; + +/*---------------------------------------------------------------------------*\ + Class cpuInfo Declaration +\*---------------------------------------------------------------------------*/ + +class cpuInfo +{ + // Private data + + // Various bits from /proc/cpuinfo + + std::string vendor_id; + std::string model_name; + int cpu_family; + int model; + float cpu_MHz; + int siblings; + int cpu_cores; + + + // Private Member Functions + + //- Parse /proc/cpuinfo + void parse(); + + //- No copy construct + cpuInfo(const cpuInfo&) = delete; + + //- No copy assignment + void operator=(const cpuInfo&) = delete; + +public: + + // Constructors + + //- Construct and populate with information + cpuInfo(); + + //- Destructor + ~cpuInfo() = default; + + + // Member Functions + + //- Write content as dictionary entries + void write(Ostream& os) const; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/cpuTime/cpuTime.H b/src/OSspecific/MSwindows/cpuTime/cpuTime.H new file mode 100644 index 00000000000..3af1aa192e9 --- /dev/null +++ b/src/OSspecific/MSwindows/cpuTime/cpuTime.H @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Typedef + Foam::cpuTime + +Description + Selection of preferred clock mechanism for the elapsed cpu time. + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuTime_H +#define cpuTime_H + +#include "cpuTimeCxx.H" +#include "cpuTimeFwd.H" + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H b/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H new file mode 100644 index 00000000000..bc7d1885f3b --- /dev/null +++ b/src/OSspecific/MSwindows/cpuTime/cpuTimeFwd.H @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Typedef + Foam::cpuTime + +Description + Selection of preferred clock mechanism for the elapsed cpu time. + +\*---------------------------------------------------------------------------*/ + +#ifndef cpuTimeFwd_H +#define cpuTimeFwd_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + class cpuTimeCxx; + + typedef cpuTimeCxx cpuTime; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C new file mode 100644 index 00000000000..425a0c333d0 --- /dev/null +++ b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.C @@ -0,0 +1,625 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2011, 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "fileMonitor.H" +#include "IOstreams.H" +#include "Pstream.H" +#include "PackedList.H" +#include "PstreamReduceOps.H" +#include "OSspecific.H" +#include "regIOobject.H" // for fileModificationSkew symbol + +#ifdef _WIN32 +#undef FOAM_USE_INOTIFY +#endif + +#ifdef FOAM_USE_INOTIFY + #include <unistd.h> + #include <sys/inotify.h> + #include <sys/ioctl.h> + #include <errno.h> + #define EVENT_SIZE ( sizeof (struct inotify_event) ) + #define EVENT_LEN (EVENT_SIZE + 16) + #define EVENT_BUF_LEN ( 1024 * EVENT_LEN ) +#endif + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +const Foam::Enum +< + Foam::fileMonitor::fileState +> +Foam::fileMonitor::fileStateNames_ +({ + { fileState::UNMODIFIED, "unmodified" }, + { fileState::MODIFIED, "modified" }, + { fileState::DELETED, "deleted" }, +}); + + +namespace Foam +{ + defineTypeNameAndDebug(fileMonitor, 0); + + //- Reduction operator for PackedList of fileState + class reduceFileStates + { + public: + unsigned int operator()(const unsigned int x, const unsigned int y) + const + { + // x,y are sets of 2bits representing fileState + + unsigned int mask = 3u; + unsigned int shift = 0; + unsigned int result = 0; + + while (mask) + { + // Combine state + unsigned int xState = (x & mask) >> shift; + unsigned int yState = (y & mask) >> shift; + + // Combine and add to result. Combine is such that UNMODIFIED + // wins. + unsigned int state = min(xState, yState); + result |= (state << shift); + + shift += 2; + mask <<= 2; + } + return result; + } + }; + + //- Combine operator for PackedList of fileState + class combineReduceFileStates + { + public: + void operator()(unsigned int& x, const unsigned int y) const + { + x = reduceFileStates()(x, y); + } + }; + + + + //- Internal tracking via stat(3p) or inotify(7) + class fileMonitorWatcher + { + public: + + const bool useInotify_; + + // For inotify + + //- File descriptor for the inotify instance + int inotifyFd_; + + //- Current watchIDs and corresponding directory id + DynamicList<label> dirWatches_; + DynamicList<fileName> dirFiles_; + + // For stat + + //- From watch descriptor to modified time + DynamicList<double> lastMod_; + + + + //- Initialise inotify + inline fileMonitorWatcher(const bool useInotify, const label sz = 20) + : + useInotify_(useInotify), + inotifyFd_(-1) + { + if (useInotify_) + { + #ifdef FOAM_USE_INOTIFY + inotifyFd_ = inotify_init(); + dirWatches_.setCapacity(sz); + dirFiles_.setCapacity(sz); + + if (inotifyFd_ < 0) + { + static bool hasWarned = false; + if (!hasWarned) + { + hasWarned = true; + WarningInFunction + << "Failed allocating an inotify descriptor : " + << string(strerror(errno)) << endl + << " Please increase the number of allowable " + << "inotify instances" << endl + << " (/proc/sys/fs/inotify/max_user_instances" + << " on Linux)" << endl + << " , switch off runTimeModifiable." << endl + << " or compile this file without " + << "FOAM_USE_INOTIFY" + << " to use time stamps instead of inotify." << endl + << " Continuing without additional file" + << " monitoring." + << endl; + } + } + #else + FatalErrorInFunction + << "You selected inotify but this file was compiled" + << " without FOAM_USE_INOTIFY" + << " Please select another fileModification test method" + << exit(FatalError); + #endif + } + else + { + lastMod_.setCapacity(sz); + } + } + + //- Remove all watches + inline ~fileMonitorWatcher() + { + #ifdef FOAM_USE_INOTIFY + if (useInotify_ && inotifyFd_ >= 0) + { + forAll(dirWatches_, i) + { + if (dirWatches_[i] >= 0) + { + if (inotify_rm_watch(inotifyFd_, int(dirWatches_[i]))) + { + WarningInFunction + << "Failed deleting directory watch " + << dirWatches_[i] << endl; + } + } + } + } + #endif + } + + inline bool addWatch(const label watchFd, const fileName& fName) + { + if (useInotify_) + { + if (inotifyFd_ < 0) + { + return false; + } + + #ifdef FOAM_USE_INOTIFY + // Add/retrieve watch on directory containing file. + // Note that fName might be non-existing in special situations + // (master-only reading for IODictionaries) + + const fileName dir = fName.path(); + + label dirWatchID = -1; + if (isDir(dir)) + { + dirWatchID = inotify_add_watch + ( + inotifyFd_, + dir.c_str(), + IN_CLOSE_WRITE + ); + + if (dirWatchID < 0) + { + FatalErrorInFunction + << "Failed adding watch " << watchFd + << " to directory " << fName << " due to " + << string(strerror(errno)) + << exit(FatalError); + } + } + + if (watchFd < dirWatches_.size() && dirWatches_[watchFd] != -1) + { + // Reuse of watchFd : should have dir watchID set to -1. + FatalErrorInFunction + << "Problem adding watch " << watchFd + << " to file " << fName + << abort(FatalError); + } + + dirWatches_(watchFd) = dirWatchID; + dirFiles_(watchFd) = fName.name(); + #endif + } + else + { + if (watchFd < lastMod_.size() && lastMod_[watchFd] != 0) + { + // Reuse of watchFd : should have lastMod set to 0. + FatalErrorInFunction + << "Problem adding watch " << watchFd + << " to file " << fName + << abort(FatalError); + } + + lastMod_(watchFd) = highResLastModified(fName); + } + + return true; + } + + inline bool removeWatch(const label watchFd) + { + if (useInotify_) + { + if (inotifyFd_ < 0) + { + return false; + } + + dirWatches_[watchFd] = -1; + } + else + { + lastMod_[watchFd] = 0; + } + return true; + } + + }; +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::fileMonitor::checkFiles() const +{ + if (useInotify_) + { + #ifdef FOAM_USE_INOTIFY + // Large buffer for lots of events + char buffer[EVENT_BUF_LEN]; + + while (true) + { + struct timeval zeroTimeout = {0, 0}; + + //- Pre-allocated structure containing file descriptors + fd_set fdSet; + // Add notify descriptor to select fd_set + FD_ZERO(&fdSet); + FD_SET(watcher_->inotifyFd_, &fdSet); + + int ready = select + ( + watcher_->inotifyFd_+1, // num filedescriptors in fdSet + &fdSet, // fdSet with only inotifyFd + nullptr, // No writefds + nullptr, // No errorfds + &zeroTimeout // eNo timeout + ); + + if (ready < 0) + { + FatalErrorInFunction + << "Problem in issuing select." + << abort(FatalError); + } + else if (FD_ISSET(watcher_->inotifyFd_, &fdSet)) + { + // Read events + ssize_t nBytes = ::read + ( + watcher_->inotifyFd_, + buffer, + EVENT_BUF_LEN + ); + + if (nBytes < 0) + { + FatalErrorInFunction + << "read of " << watcher_->inotifyFd_ + << " failed with " << label(nBytes) + << abort(FatalError); + } + + // Go through buffer, consuming events + int i = 0; + while (i < nBytes) + { + const struct inotify_event* inotifyEvent = + reinterpret_cast<const struct inotify_event*> + ( + &buffer[i] + ); + + //Pout<< "watchFd:" << inotifyEvent->wd << nl + // << "mask:" << inotifyEvent->mask << nl + // << endl; + //Pout<< "file:" << fileName(inotifyEvent->name) << endl; + //Pout<< "len:" << inotifyEvent->len << endl; + + if + ( + (inotifyEvent->mask & IN_CLOSE_WRITE) + && inotifyEvent->len + ) + { + // Search for file + forAll(watcher_->dirWatches_, i) + { + label id = watcher_->dirWatches_[i]; + if + ( + id == inotifyEvent->wd + && inotifyEvent->name == watcher_->dirFiles_[i] + ) + { + // Correct directory and name + localState_[i] = MODIFIED; + } + } + } + + i += EVENT_SIZE + inotifyEvent->len; + } + } + else + { + // No data + return; + } + } + #endif + } + else + { + forAll(watcher_->lastMod_, watchFd) + { + double oldTime = watcher_->lastMod_[watchFd]; + + if (oldTime != 0) + { + const fileName& fName = watchFile_[watchFd]; + double newTime = highResLastModified(fName); + + if (newTime == 0) + { + localState_[watchFd] = DELETED; + } + else + { + if (newTime > (oldTime + regIOobject::fileModificationSkew)) + { + localState_[watchFd] = MODIFIED; + } + else + { + localState_[watchFd] = UNMODIFIED; + } + } + } + } + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + + +Foam::fileMonitor::fileMonitor(const bool useInotify) +: + useInotify_(useInotify), + localState_(20), + state_(20), + watchFile_(20), + freeWatchFds_(2), + watcher_(new fileMonitorWatcher(useInotify_, 20)) +{} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::fileMonitor::~fileMonitor() +{} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +// Note: fName might not exist (on slaves if in master-only mode for +// regIOobject) +Foam::label Foam::fileMonitor::addWatch(const fileName& fName) +{ + label watchFd; + + label sz = freeWatchFds_.size(); + + if (sz) + { + watchFd = freeWatchFds_[sz-1]; + freeWatchFds_.setSize(sz-1); + } + else + { + watchFd = state_.size(); + } + + watcher_->addWatch(watchFd, fName); + + if (debug) + { + Pout<< "fileMonitor : added watch " << watchFd << " on file " + << fName << endl; + } + + if (watchFd < 0) + { + WarningInFunction + << "could not add watch for file " << fName << endl; + } + else + { + localState_(watchFd) = UNMODIFIED; + state_(watchFd) = UNMODIFIED; + watchFile_(watchFd) = fName; + } + return watchFd; +} + + +bool Foam::fileMonitor::removeWatch(const label watchFd) +{ + if (debug) + { + Pout<< "fileMonitor : removing watch " << watchFd << " on file " + << watchFile_[watchFd] << endl; + } + + freeWatchFds_.append(watchFd); + return watcher_->removeWatch(watchFd); +} + + +const Foam::fileName& Foam::fileMonitor::getFile(const label watchFd) const +{ + return watchFile_[watchFd]; +} + + +Foam::fileMonitor::fileState Foam::fileMonitor::getState(const label watchFd) +const +{ + return state_[watchFd]; +} + + +void Foam::fileMonitor::updateStates +( + const bool masterOnly, + const bool syncPar +) const +{ + if (Pstream::master() || !masterOnly) + { + // Update the localState_ + checkFiles(); + } + + if (syncPar) + { + // Pack local state (might be on master only) + PackedList<2> stats(state_.size(), MODIFIED); + if (Pstream::master() || !masterOnly) + { + forAll(state_, watchFd) + { + stats.set + ( + watchFd, + static_cast<unsigned int>(localState_[watchFd]) + ); + } + } + + + // Scatter or reduce to synchronise state + if (masterOnly) + { + // Scatter + if (stats.storage().size() == 1) + { + Pstream::scatter(stats.storage()[0]); + } + else + { + Pstream::listCombineScatter(stats.storage()); + } + } + else + { + // Reduce + if (stats.storage().size() == 1) + { + // Optimisation valid for most cases. + reduce(stats.storage()[0], reduceFileStates()); + } + else + { + Pstream::listCombineGather + ( + stats.storage(), + combineReduceFileStates() + ); + } + } + + + // Update synchronised state + forAll(state_, watchFd) + { + // Assign synchronised state + unsigned int stat = stats[watchFd]; + state_[watchFd] = fileState(stat); + + if (!masterOnly) + { + // Give warning for inconsistent state + if (state_[watchFd] != localState_[watchFd]) + { + if (debug) + { + Pout<< "fileMonitor : Delaying reading " + << watchFile_[watchFd] + << " due to inconsistent " + "file time-stamps between processors" + << endl; + } + + WarningInFunction + << "Delaying reading " << watchFile_[watchFd] + << " due to inconsistent " + "file time-stamps between processors" << endl; + } + } + } + } + else + { + state_ = localState_; + } +} + + +void Foam::fileMonitor::setUnmodified(const label watchFd) +{ + state_[watchFd] = UNMODIFIED; + localState_[watchFd] = UNMODIFIED; + + if (!useInotify_) + { + watcher_->lastMod_[watchFd] = highResLastModified(watchFile_[watchFd]); + } +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/fileMonitor/fileMonitor.H b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.H new file mode 100644 index 00000000000..38673a7d0ba --- /dev/null +++ b/src/OSspecific/MSwindows/fileMonitor/fileMonitor.H @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010, 2017-2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileMonitor + +Description + Checking for changes to files. + +Note + The default is to use stat to get the timestamp. + + Compile with FOAM_USE_INOTIFY to use the inotify + (Linux specific, since 2.6.13) framework. The problem is that inotify does + not work on nfs3 mounted directories!! + +SourceFiles + fileMonitor.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fileMonitor_H +#define fileMonitor_H + +#include <sys/types.h> +#include "Enum.H" +#include "className.H" +#include "DynamicList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class fileMonitor; +class fileMonitorWatcher; + +/*---------------------------------------------------------------------------*\ + Class fileMonitor Declaration +\*---------------------------------------------------------------------------*/ + +class fileMonitor +{ +public: + + // Public data types + + //- Enumeration defining the file state. + enum fileState + { + UNMODIFIED = 0, + MODIFIED = 1, + DELETED = 2 + }; + + static const Enum<fileState> fileStateNames_; + +private: + + // Private data + + //- Whether to use inotify (requires -DFOAM_USE_INOTIFY, see above) + const bool useInotify_; + + //- State for all watchFds based on local files + mutable DynamicList<fileState> localState_; + + //- State for all watchFds - synchronised + mutable DynamicList<fileState> state_; + + //- Filename for all watchFds + DynamicList<fileName> watchFile_; + + //- Free watchFds + DynamicList<label> freeWatchFds_; + + //- Watch mechanism (stat or inotify) + mutable autoPtr<fileMonitorWatcher> watcher_; + + + // Private Member Functions + + //- Update localState_ from any events. + void checkFiles() const; + + //- No copy construct + fileMonitor(const fileMonitor&) = delete; + + //- No copy assignment + void operator=(const fileMonitor&) = delete; + + +public: + + // Declare name of the class and its debug switch + ClassName("fileMonitor"); + + // Constructors + + //- Construct null + fileMonitor(const bool useInotify); + + + //- Destructor + ~fileMonitor(); + + + // Member Functions + + //- Add file to watch. Return watch descriptor + label addWatch(const fileName&); + + //- Remove file to watch. Return true if successful + bool removeWatch(const label watchFd); + + //- Get name of file being watched + const fileName& getFile(const label watchFd) const; + + //- Check state using handle + fileState getState(const label watchFd) const; + + //- Check state of all files. Updates state_. + void updateStates + ( + const bool masterOnly, + const bool syncPar + ) const; + + //- Reset state (e.g. after having read it) using handle + void setUnmodified(const label watchFd); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/fileStat/fileStat.C b/src/OSspecific/MSwindows/fileStat/fileStat.C new file mode 100644 index 00000000000..2293653ad12 --- /dev/null +++ b/src/OSspecific/MSwindows/fileStat/fileStat.C @@ -0,0 +1,214 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "fileStat.H" +#include "IOstreams.H" +#include "timer.H" + +#include <unistd.h> + +#undef major +#undef minor +#undef makedev + +#define major(dev) int(((dev) >> 8) & 0xff) +#define minor(dev) int((dev) & 0xff) +#define makedev(majNum, minNum) (((unsigned(majNum)) << 8) | (unsigned(minNum))) + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::fileStat::fileStat() +: + valid_(false) +{} + + +Foam::fileStat::fileStat +( + const char* fName, + const bool followLink, + const unsigned int maxTime +) +: + valid_(false) +{ + if (!fName || !fName[0]) + { + return; + } + + // Work on volatile + volatile bool locIsValid = false; + + timer myTimer(maxTime); + + if (!timedOut(myTimer)) + { + #ifdef _WIN32 + locIsValid = (::stat(fName, &status_) == 0); + #else + if (followLink) + { + locIsValid = (::stat(fName, &status_) == 0); + } + else + { + locIsValid = (::lstat(fName, &status_) == 0); + } + #endif + } + + // Copy into (non-volatile, possible register based) member var + valid_ = locIsValid; +} + + +Foam::fileStat::fileStat +( + const fileName& fName, + const bool followLink, + const unsigned int maxTime +) +: + fileStat(fName.c_str(), followLink, maxTime) +{} + + +Foam::fileStat::fileStat(Istream& is) +{ + is >> *this; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::label Foam::fileStat::size() const +{ + return valid_ ? label(status_.st_size) : 0; +} + + +time_t Foam::fileStat::modTime() const +{ + return valid_ ? status_.st_mtime : 0; +} + + +double Foam::fileStat::dmodTime() const +{ + return + ( + valid_ + ? + #ifdef __APPLE__ + (status_.st_mtime + 1e-9*status_.st_mtimespec.tv_nsec) + #elif defined (_WIN32) + (status_.st_mtime) + #else + (status_.st_mtime + 1e-9*status_.st_mtim.tv_nsec) + #endif + : 0 + ); +} + + +bool Foam::fileStat::sameDevice(const fileStat& other) const +{ + return + valid_ + && ( + major(status_.st_dev) == major(other.status_.st_dev) + && minor(status_.st_dev) == minor(other.status_.st_dev) + ); +} + + +bool Foam::fileStat::sameINode(const fileStat& other) const +{ + return valid_ && (status_.st_ino == other.status_.st_ino); +} + + +bool Foam::fileStat::sameINode(const label iNode) const +{ + return valid_ && (status_.st_ino == ino_t(iNode)); +} + + +// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, fileStat& fs) +{ + FixedList<label, 13> list(is); + + fs.valid_ = list[0]; + + dev_t st_dev = makedev(list[1], list[2]); + fs.status_.st_dev = st_dev; + + fs.status_.st_ino = list[3]; + fs.status_.st_mode = list[4]; + fs.status_.st_uid = list[5]; + fs.status_.st_gid = list[6]; + + dev_t st_rdev = makedev(list[7], list[8]); + fs.status_.st_rdev = st_rdev; + + fs.status_.st_size = list[9]; + fs.status_.st_atime = list[10]; + fs.status_.st_mtime = list[11]; + fs.status_.st_ctime = list[12]; + + is.check(FUNCTION_NAME); + return is; +} + + +Foam::Ostream& Foam::operator<<(Ostream& os, const fileStat& fs) +{ + FixedList<label, 13> list; + + list[0] = label(fs.valid_); + list[1] = label(major(fs.status_.st_dev)); + list[2] = label(minor(fs.status_.st_dev)); + list[3] = label(fs.status_.st_ino); + list[4] = label(fs.status_.st_mode); + list[5] = label(fs.status_.st_uid); + list[6] = label(fs.status_.st_gid); + list[7] = label(major(fs.status_.st_rdev)); + list[8] = label(minor(fs.status_.st_rdev)); + list[9] = label(fs.status_.st_size); + list[10] = label(fs.status_.st_atime); + list[11] = label(fs.status_.st_mtime); + list[12] = label(fs.status_.st_ctime); + + return os << list; +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/fileStat/fileStat.H b/src/OSspecific/MSwindows/fileStat/fileStat.H new file mode 100644 index 00000000000..bd736322774 --- /dev/null +++ b/src/OSspecific/MSwindows/fileStat/fileStat.H @@ -0,0 +1,180 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2010, 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::fileStat + +Description + Wrapper for stat() and lstat() system calls. + +Warning + On Linux (an maybe on others) a stat() of an nfs mounted (remote) + file does never timeout and cannot be interrupted! + So e.g. Foam::ping first and hope nfs is running. + +SourceFiles + fileStat.C + +\*---------------------------------------------------------------------------*/ + +#ifndef fileStat_H +#define fileStat_H + +#include <sys/stat.h> +#include <sys/types.h> + +#include "label.H" +#include "fileName.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declarations +class fileStat; + +Istream& operator>>(Istream& is, fileStat& fs); +Ostream& operator<<(Ostream& os, const fileStat& fs); + + +/*---------------------------------------------------------------------------*\ + Class fileStat Declaration +\*---------------------------------------------------------------------------*/ + +class fileStat +{ + // Private data + + struct stat status_; + + bool valid_; + + +public: + + // Constructors + + //- Empty constructor + fileStat(); + + //- Construct from components. + // + // \param fName The file name or directory name to stat. + // \param followLink If it is a link, get the status of the source + // file/directory. + // \param maxTime The timeout value. + // + // \note An empty filename is a no-op. + fileStat + ( + const char* fName, + const bool followLink = true, + const unsigned int maxTime = 0 + ); + + //- Construct from components. + // + // \param fName The file name or directory name to stat. + // \param followLink If it is a link, get the status of the source + // file/directory. + // \param maxTime The timeout value. + // + // \note An empty filename is a no-op. + fileStat + ( + const fileName& fName, + const bool followLink = true, + const unsigned int maxTime = 0 + ); + + //- Construct from Istream + explicit fileStat(Istream& is); + + + // Member Functions + + // Access + + //- Raw status + const struct stat& status() const + { + return status_; + } + + //- Was file-stat successful? + bool valid() const + { + return valid_; + } + + //- Size in bytes. Zero for an invalid file-stat. + label size() const; + + //- Return the modification time in seconds. + // Zero for an invalid file-stat. + time_t modTime() const; + + //- Return the modification time in seconds (nanosecond resolution) + // Zero for an invalid file-stat. + double dmodTime() const; + + + // Check + + //- Compare two fileStats for same device + bool sameDevice(const fileStat& other) const; + + //- Compare two fileStats for same Inode + bool sameINode(const fileStat& other) const; + + //- Compare state against inode + bool sameINode(const label iNode) const; + + + // IOstream Operators + + friend Istream& operator>>(Istream& is, fileStat& fs); + friend Ostream& operator<<(Ostream& os, const fileStat& fs); + + + // Housekeeping + + //- Deprecated(2019-04) Was file-stat successful? + // \deprecated(2019-04) - use valid() method + bool isValid() const { return valid_; } + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/memInfo/memInfo.C b/src/OSspecific/MSwindows/memInfo/memInfo.C new file mode 100644 index 00000000000..62f86568a8c --- /dev/null +++ b/src/OSspecific/MSwindows/memInfo/memInfo.C @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010, 2016-2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "memInfo.H" +#include "OSspecific.H" +#include "IOstreams.H" + +#include <fstream> +#include <string> + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::memInfo::memInfo() +: + peak_(0), + size_(0), + rss_(0), + free_(0) +{ + update(); +} + + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::memInfo::valid() const +{ + return peak_ > 0; +} + + +void Foam::memInfo::clear() +{ + peak_ = size_ = rss_ = 0; + free_ = 0; +} + + +const Foam::memInfo& Foam::memInfo::update() +{ + clear(); + + // Not supported under Windows + + return *this; +} + + +void Foam::memInfo::write(Ostream& os) const +{ + os.writeEntry("size", size_); + os.writeEntry("peak", peak_); + os.writeEntry("rss", rss_); + os.writeEntry("free", free_); +} + + +// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * // + +Foam::Istream& Foam::operator>>(Istream& is, memInfo& m) +{ + is.readBegin("memInfo"); + is >> m.peak_ >> m.size_ >> m.rss_ >> m.free_; + is.readEnd("memInfo"); + + is.check(FUNCTION_NAME); + return is; +} + + +Foam::Ostream& Foam::operator<<(Ostream& os, const memInfo& m) +{ + os << token::BEGIN_LIST + << m.peak_ << token::SPACE + << m.size_ << token::SPACE + << m.rss_ << token::SPACE + << m.free_ + << token::END_LIST; + + os.check(FUNCTION_NAME); + return os; +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/memInfo/memInfo.H b/src/OSspecific/MSwindows/memInfo/memInfo.H new file mode 100644 index 00000000000..9e262103382 --- /dev/null +++ b/src/OSspecific/MSwindows/memInfo/memInfo.H @@ -0,0 +1,151 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2010-2010, 2016-2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::memInfo + +Description + Memory usage information for the current process, and the system memory + that is free. + +Note + Windows variant does nothing. + +SourceFiles + memInfo.C + +\*---------------------------------------------------------------------------*/ + +#ifndef memInfo_H +#define memInfo_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration of friend functions and operators +class memInfo; +class Istream; +class Ostream; + +Istream& operator>>(Istream& is, memInfo& m); +Ostream& operator<<(Ostream& os, const memInfo& m); + + +/*---------------------------------------------------------------------------*\ + Class memInfo Declaration +\*---------------------------------------------------------------------------*/ + +class memInfo +{ + // Private data + + //- Peak memory used by the process (VmPeak in /proc/PID/status) + int peak_; + + //- Memory used by the process (VmSize in /proc/PID/status) + int size_; + + //- Resident set size of the process (VmRSS in /proc/PID/status) + int rss_; + + //- System memory free (MemFree in /proc/meminfo) + int free_; + +public: + + // Constructors + + //- Construct and populate with values + memInfo(); + + + //- Destructor + ~memInfo() = default; + + + // Member Functions + + //- True if the memory information appears valid + bool valid() const; + + //- Reset to zero + void clear(); + + //- Update according to /proc/PID/status and /proc/memory contents + const memInfo& update(); + + + //- Peak memory (VmPeak in /proc/PID/status) at last update() + inline int peak() const + { + return peak_; + } + + //- Memory size (VmSize in /proc/PID/status) at last update() + inline int size() const + { + return size_; + } + + //- Resident set size (VmRSS in /proc/PID/status) at last update() + inline int rss() const + { + return rss_; + } + + //- System memory free (MemFree in /proc/meminfo) + inline int free() const + { + return free_; + } + + + // Write + + //- Write content as dictionary entries + void write(Ostream& os) const; + + + // IOstream Operators + + //- Read peak/size/rss from stream + friend Istream& operator>>(Istream& is, memInfo& m); + + //- Write peak/size/rss to stream + friend Ostream& operator<<(Ostream& os, const memInfo& m); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/printStack/dummyPrintStack.C b/src/OSspecific/MSwindows/printStack/dummyPrintStack.C new file mode 100644 index 00000000000..fbbf9d8278c --- /dev/null +++ b/src/OSspecific/MSwindows/printStack/dummyPrintStack.C @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2017 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "error.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +void Foam::error::safePrintStack(std::ostream& os) +{} + + +void Foam::error::printStack(Ostream& os) +{} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/regExp/regExp.H b/src/OSspecific/MSwindows/regExp/regExp.H new file mode 100644 index 00000000000..b608dd298a4 --- /dev/null +++ b/src/OSspecific/MSwindows/regExp/regExp.H @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Typedef + Foam::regExp + +Description + Selection of preferred regular expression implementation + +\*---------------------------------------------------------------------------*/ + +#ifndef regExp_H +#define regExp_H + +#include "regExpCxx.H" +#include "regExpFwd.H" + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/regExp/regExpFwd.H b/src/OSspecific/MSwindows/regExp/regExpFwd.H new file mode 100644 index 00000000000..ff16d901182 --- /dev/null +++ b/src/OSspecific/MSwindows/regExp/regExpFwd.H @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Typedef + Foam::regExp + +Description + Selection of preferred regular expression implementation + +\*---------------------------------------------------------------------------*/ + +#ifndef regExpFwd_H +#define regExpFwd_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + class regExpCxx; + + typedef regExpCxx regExp; +} + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigFpe.C b/src/OSspecific/MSwindows/signals/sigFpe.C new file mode 100644 index 00000000000..177dafc1619 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigFpe.C @@ -0,0 +1,235 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2016-2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "sigFpe.H" +#include "error.H" +#include "JobInfo.H" +#include "OSspecific.H" +#include "IOstreams.H" +#include "Switch.H" +#include "UList.H" + +#include <float.h> // For *fp functions +#include <limits> + +// File-local functions +#include "signalMacros.C" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +bool Foam::sigFpe::switchFpe_(Foam::debug::optimisationSwitch("trapFpe", 0)); +bool Foam::sigFpe::switchNan_(Foam::debug::optimisationSwitch("setNaN", 0)); + +bool Foam::sigFpe::sigActive_ = false; +bool Foam::sigFpe::nanActive_ = false; + +// Saved old FPE signal trapping setting (file-local variable) +static unsigned int oldFpe_ = 0u; + + +static void clearFpe() +{ + #ifndef Foam_no_sigFpe + _clearfp(); + _controlfp(oldFpe_, 0xFFFFFFFF); + #endif +} + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +// Can turn on/off via env variable containing a bool (true|false|on|off ...) +// or by the specified flag +static bool isTrue(const char* envName, bool deflt) +{ + const auto str(Foam::getEnv(envName)); + + if (str.size()) + { + Foam::Switch sw(str, true); // Silently ignores bad input + + if (sw.valid()) + { + return sw; + } + } + + // Env was not set or did not contain a valid bool value + return deflt; +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigFpe::sigHandler(int) +{ + resetHandler("SIGFPE", SIGFPE); + + jobInfo.signalEnd(); // Update jobInfo file + error::printStack(Perr); + clearFpe(); + ::raise(SIGFPE); // Throw signal (to old handler) +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigFpe::sigFpe() +{ + set(false); +} + + +Foam::sigFpe::ignore::ignore() +: + wasActive_(sigFpe::active()) +{ + if (wasActive_) + { + sigFpe::unset(); + } +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigFpe::~sigFpe() +{ + unset(false); +} + + +Foam::sigFpe::ignore::~ignore() +{ + restore(); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::sigFpe::ignore::restore() +{ + if (wasActive_) + { + sigFpe::set(); + } + wasActive_ = false; +} + + +bool Foam::sigFpe::requested() +{ + return isTrue("FOAM_SIGFPE", switchFpe_); +} + + +void Foam::sigFpe::set(bool verbose) +{ + if (!sigActive_ && requested()) + { + #ifdef Foam_no_sigFpe + + if (verbose) + { + Info<< "trapFpe: Floating point exception trapping "; + Info<< "- disabled on this platform" << endl; + } + + #else + + oldFpe_ = _controlfp(0, 0); + + const unsigned int newFpe = + ( + oldFpe_ & ~(_EM_ZERODIVIDE | _EM_INVALID | _EM_OVERFLOW) + ); + + _controlfp(newFpe, _MCW_EM); + + setHandler("SIGFPE", SIGFPE, sigHandler); + + sigActive_ = true; + + if (verbose) + { + Info<< "trapFpe: Floating point exception trapping "; + + if (sigActive_) + { + Info<< "enabled (FOAM_SIGFPE)." << endl; + } + else + { + Info<< "- not supported on this platform" << endl; + } + } + #endif + } + + + nanActive_ = false; + if (isTrue("FOAM_SETNAN", switchNan_)) + { + if (verbose) + { + Info<< "setNaN : Initialise allocated memory to NaN " + << "- not supported on this platform" << endl; + } + } +} + + +void Foam::sigFpe::unset(bool verbose) +{ + if (sigActive_) + { + if (verbose) + { + Info<< "sigFpe : Disabling floating point exception trapping" + << endl; + } + + sigActive_ = false; + + clearFpe(); + + resetHandler("SIGFPE", SIGFPE); + } + + nanActive_ = false; +} + + +void Foam::sigFpe::fillNan(UList<scalar>& list) +{ + list = std::numeric_limits<scalar>::signaling_NaN(); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigFpe.H b/src/OSspecific/MSwindows/signals/sigFpe.H new file mode 100644 index 00000000000..67c23d4cb2e --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigFpe.H @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2018-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::sigFpe + +Description + Set up trapping for floating point exceptions (signal FPE). + + Defined by controlDict InfoSwitch entries: + - \par trapFpe + Enable floating point exception trapping. + + - \par setNaN + Initialization all malloced memory to NaN. + Combined with \c trapFpe, this causes usage of uninitialized scalars + to trigger an abort. + + Environment variables: + - \par FOAM_SIGFPE (true|false) + overrides \c trapFpe + - \par FOAM_SETNAN (true|false) + overrides \c setNaN + + Note that trapping can be set/removed through the static member functions + or through the scope of the object (constructor sets trapping; destructor + restores original). The class behaves as a singleton. + +SourceFiles + sigFpe.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigFpe_H +#define sigFpe_H + +#include "scalar.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +template<class T> class UList; + +/*---------------------------------------------------------------------------*\ + Class sigFpe Declaration +\*---------------------------------------------------------------------------*/ + +class sigFpe +{ + // Private Data + + //- Flag that floating point trapping should be used. + // Can override with FOAM_SIGFPE env variable + static bool switchFpe_; + + //- Flag that NaN initialisation should be used. + // Can override with FOAM_SETNAN env variable + static bool switchNan_; + + //- Floating point trapping currently active? + static bool sigActive_; + + //- Flag to indicate mallocNan is currently active + static bool nanActive_; + + + // Private Member Functions + + //- Handler for caught signals - ends job and prints stack + static void sigHandler(int); + + +public: + + // Constructors + + //- Constructor calls set() to activate the FPE signal handler if it + //- was was not previously activate and requested() returns true. + sigFpe(); + + + //- Destructor calls unset() to deactivate the FPE signal handler + //- as required. + ~sigFpe(); + + + // Static Member Functions + + //- Check if SIGFPE signals handler is to be enabled. + // This is controlled by the trapFpe entry or the FOAM_SIGFPE + // environment variable + static bool requested(); + + //- True if SIGFPE handling is currently active. + static inline bool active() + { + return sigActive_; + } + + //- True if NaN memory initialisation is currently active. + static inline bool nanActive() + { + return nanActive_; + } + + //- Activate SIGFPE signal handler when FOAM_SIGFPE is %set + // Fill memory with NaN when FOAM_SETNAN is %set + static void set(bool verbose=false); + + //- Deactivate SIGFPE signal handler and NaN memory initialisation + static void unset(bool verbose=false); + + //- Fill data block with NaN values + static void fillNan(UList<scalar>& list); + + + // Helper classes + + //- Helper to locally ignore SIGFPE handling. + // Restores the original state of the SIGFPE handler on destruction. + class ignore + { + //- The signal handler state when entering + bool wasActive_; + + //- No copy construct + ignore(const ignore&) = delete; + + //- No copy assignment + void operator=(const ignore&) = delete; + + //- No move construct + ignore(ignore&&) = delete; + + //- No move assignment + void operator=(ignore&&) = delete; + + + public: + + //- Constructor deactivates any previously active SIGFPE handler + ignore(); + + //- Destructor restores the original state of SIGFPE handler + ~ignore(); + + //- Restore the original state of SIGFPE handler + void restore(); + }; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigInt.C b/src/OSspecific/MSwindows/signals/sigInt.C new file mode 100644 index 00000000000..0118051cc6f --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigInt.C @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2018-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "sigInt.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" + +// File-local functions +#include "signalMacros.C" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +bool Foam::sigInt::sigActive_ = false; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigInt::sigHandler(int) +{ + resetHandler("SIGINT", SIGINT); + + jobInfo.signalEnd(); // Update jobInfo file + ::raise(SIGINT); // Throw signal (to old handler) +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigInt::sigInt() +{ + set(false); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigInt::~sigInt() +{ + unset(false); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::sigInt::set(bool) +{ + if (sigActive_) + { + return; + } + sigActive_ = true; + + setHandler("SIGINT", SIGINT, sigHandler); +} + + +void Foam::sigInt::unset(const bool verbose) +{ + if (!sigActive_) + { + return; + } + sigActive_ = false; + + resetHandler("SIGINT", SIGINT); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigInt.H b/src/OSspecific/MSwindows/signals/sigInt.H new file mode 100644 index 00000000000..2e9e1758a01 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigInt.H @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2018-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::sigInt + +Description + Signal handler for INT interupt. + + The standard interupt handler is overridden to ensure that the + runningJob file is removed. + + Can be used either directly through the static member functions or + through the scope of the object (constructor sets trapping; destructor + restores original). + +See also + Foam::JobInfo + +SourceFiles + sigInt.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigInt_H +#define sigInt_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class sigInt Declaration +\*---------------------------------------------------------------------------*/ + +class sigInt +{ + // Private data + + //- Signal trapping enabled? + static bool sigActive_; + + + // Private Member Functions + + static void sigHandler(int); + + +public: + + // Constructors + + //- Construct null + sigInt(); + + + //- Destructor + ~sigInt(); + + + // Member functions + + //- Activate SIGINT signal handler + static void set(bool verbose=false); + + //- Deactivate SIGINT signal handler + static void unset(bool verbose=false); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigQuit.C b/src/OSspecific/MSwindows/signals/sigQuit.C new file mode 100644 index 00000000000..2a73744d002 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigQuit.C @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2018-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "sigQuit.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" + +// File-local functions +#include "signalMacros.C" + +// NOTE: SIGBREAK is the best alternative to SIGQUIT on windows + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +bool Foam::sigQuit::sigActive_ = false; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigQuit::sigHandler(int) +{ + resetHandler("SIGBREAK", SIGBREAK); + + jobInfo.signalEnd(); // Update jobInfo file + error::printStack(Perr); + ::raise(SIGBREAK); // Throw signal (to old handler) +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigQuit::sigQuit() +{ + set(false); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigQuit::~sigQuit() +{ + unset(false); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::sigQuit::set(bool) +{ + if (sigActive_) + { + return; + } + sigActive_ = true; + + setHandler("SIGBREAK", SIGBREAK, sigHandler); +} + + +void Foam::sigQuit::unset(bool) +{ + if (!sigActive_) + { + return; + } + sigActive_ = false; + + resetHandler("SIGBREAK", SIGBREAK); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigQuit.H b/src/OSspecific/MSwindows/signals/sigQuit.H new file mode 100644 index 00000000000..2f8888d090a --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigQuit.H @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2017-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::sigQuit + +Description + Signal handler for QUIT interupt. + + The standard interupt handler is overridden to ensure that the + runningJob file is removed. + Can be used either directly through the static member functions or + through the scope of the object (constructor sets trapping; destructor + restores original). + +See also + Foam::JobInfo + +SourceFiles + sigQuit.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigQuit_H +#define sigQuit_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class sigQuit Declaration +\*---------------------------------------------------------------------------*/ + +class sigQuit +{ + // Private Data + + //- Signal trapping enabled? + static bool sigActive_; + + + // Private Member Functions + + //- Handler for caught signals + static void sigHandler(int); + + +public: + + // Constructors + + //- Construct null + sigQuit(); + + + //- Destructor + ~sigQuit(); + + + // Member Functions + + //- Activate SIGQUIT signal handler + static void set(bool verbose=false); + + //- Deactivate SIGQUIT signal handler + static void unset(bool verbose=false); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigSegv.C b/src/OSspecific/MSwindows/signals/sigSegv.C new file mode 100644 index 00000000000..6c1a3f36324 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigSegv.C @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2018-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "sigSegv.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" + +// File-local functions +#include "signalMacros.C" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +bool Foam::sigSegv::sigActive_ = false; + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigSegv::sigHandler(int) +{ + resetHandler("SIGSEGV", SIGSEGV); + + jobInfo.signalEnd(); // Update jobInfo file + error::printStack(Perr); + ::raise(SIGSEGV); // Throw signal (to old handler) +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigSegv::sigSegv() +{ + set(false); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigSegv::~sigSegv() +{ + unset(false); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::sigSegv::set(bool) +{ + if (sigActive_) + { + return; + } + sigActive_ = true; + + setHandler("SIGSEGV", SIGSEGV, sigHandler); +} + + +void Foam::sigSegv::unset(bool) +{ + if (!sigActive_) + { + return; + } + sigActive_ = false; + + resetHandler("SIGSEGV", SIGSEGV); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigSegv.H b/src/OSspecific/MSwindows/signals/sigSegv.H new file mode 100644 index 00000000000..ff4a8f3ab75 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigSegv.H @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2018-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::sigSegv + +Description + Signal handler for SEGV interupt. + + The standard interupt handler is overridden to ensure that the + runningJob file is removed. + Can be used either directly through the static member functions or + through the scope of the object (constructor sets trapping; destructor + restores original). + +See also + Foam::JobInfo + +SourceFiles + sigSegv.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigSegv_H +#define sigSegv_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class sigSegv Declaration +\*---------------------------------------------------------------------------*/ + +class sigSegv +{ + // Private Data + + //- Signal trapping enabled? + static bool sigActive_; + + + // Private Member Functions + + //- Handler for caught signals + static void sigHandler(int); + + +public: + + // Constructors + + //- Construct null + sigSegv(); + + + //- Destructor + ~sigSegv(); + + + // Member functions + + //- Activate SIGSEGV signal handler + static void set(bool verbose=false); + + //- Deactivate SIGSEGV signal handler + static void unset(bool verbose=false); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C b/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C new file mode 100644 index 00000000000..0a459b27210 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.C @@ -0,0 +1,174 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "sigWriteNow.H" +#include "sigStopAtWriteNow.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" +#include "Time.H" + +// File-local functions +#include "signalMacros.C" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Signal number to catch +int Foam::sigStopAtWriteNow::signal_ +( + Foam::debug::optimisationSwitch("stopAtWriteNowSignal", -1) +); + +// Pointer to Time (file-local variable) +static Foam::Time const* runTimePtr_ = nullptr; + + +// * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * * // + +namespace Foam +{ +// Register re-reader +struct addstopAtWriteNowSignalToOpt +: + public ::Foam::simpleRegIOobject +{ + addstopAtWriteNowSignalToOpt(const char* name) + : + ::Foam::simpleRegIOobject(Foam::debug::addOptimisationObject, name) + {} + + virtual ~addstopAtWriteNowSignalToOpt() = default; + + virtual void readData(Foam::Istream& is) + { + sigStopAtWriteNow::signal_ = readLabel(is); + sigStopAtWriteNow::set(true); + } + + virtual void writeData(Foam::Ostream& os) const + { + os << sigStopAtWriteNow::signal_; + } +}; + +addstopAtWriteNowSignalToOpt addstopAtWriteNowSignalToOpt_ +( + "stopAtWriteNowSignal" +); + +} // End namespace Foam + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigStopAtWriteNow::sigHandler(int) +{ + resetHandler("stopAtWriteNow", signal_); + + jobInfo.signalEnd(); // Update jobInfo file + + if (runTimePtr_) + { + Info<< "sigStopAtWriteNow :" + << " setting up write and stop at end of the next iteration" + << nl << endl; + runTimePtr_->stopAt(Time::saWriteNow); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigStopAtWriteNow::sigStopAtWriteNow() +{} + + +Foam::sigStopAtWriteNow::sigStopAtWriteNow(const Time& runTime, bool verbose) +{ + runTimePtr_ = &runTime; // Store runTime + set(verbose); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigStopAtWriteNow::~sigStopAtWriteNow() +{ + if (!active()) + { + return; + } + + resetHandler("stopAtWriteNow", signal_); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::sigStopAtWriteNow::active() +{ + return signal_ > 0; +} + + +int Foam::sigStopAtWriteNow::signalNumber() +{ + return signal_; +} + + +void Foam::sigStopAtWriteNow::set(bool verbose) +{ + if (!active()) + { + return; + } + + + // Check that the signal is different from the writeNowSignal + if (sigWriteNow::signalNumber() == signal_) + { + FatalErrorInFunction + << "stopAtWriteNowSignal : " << signal_ + << " cannot be the same as the writeNowSignal." + << " Please change this in the etc/controlDict." + << exit(FatalError); + } + + if (verbose) + { + Info<< "sigStopAtWriteNow :" + << " Enabling writing and stopping upon signal " << signal_ + << endl; + } + + setHandler("stopAtWriteNow", signal_, sigHandler); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.H b/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.H new file mode 100644 index 00000000000..0464a6d52a4 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigStopAtWriteNow.H @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::sigStopAtWriteNow + +Description + Signal handler to write and stop the job. + The interrupt is defined by OptimisationSwitches::stopAtWriteNowSignal + +SourceFiles + sigStopAtWriteNow.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigStopAtWriteNow_H +#define sigStopAtWriteNow_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class Time; + +/*---------------------------------------------------------------------------*\ + Class sigStopAtWriteNow Declaration +\*---------------------------------------------------------------------------*/ + +class sigStopAtWriteNow +{ + // Private Data + + //- Signal number to use + static int signal_; + + + // Private Member Functions + + //- Handler for caught signals + static void sigHandler(int); + + +public: + + //- Allow setter access to signal_ + friend class addstopAtWriteNowSignalToOpt; + + + // Constructors + + //- Construct null + sigStopAtWriteNow(); + + //- Construct from components + sigStopAtWriteNow(const Time& runTime, bool verbose=false); + + + //- Destructor + ~sigStopAtWriteNow(); + + + // Member Functions + + //- Is active? + static bool active(); + + //- Signal number being used + static int signalNumber(); + + //- Set/reset signal handler + static void set(bool verbose=false); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigWriteNow.C b/src/OSspecific/MSwindows/signals/sigWriteNow.C new file mode 100644 index 00000000000..71d309adc5d --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigWriteNow.C @@ -0,0 +1,154 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "sigWriteNow.H" +#include "error.H" +#include "JobInfo.H" +#include "IOstreams.H" +#include "Time.H" + +// File-local functions +#include "signalMacros.C" + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +// Signal number to catch +int Foam::sigWriteNow::signal_ +( + Foam::debug::optimisationSwitch("writeNowSignal", -1) +); + +// Pointer to Time (file-local variable) +static Foam::Time* runTimePtr_ = nullptr; + + +// * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Register re-reader +struct addwriteNowSignalToOpt +: + public ::Foam::simpleRegIOobject +{ + addwriteNowSignalToOpt(const char* name) + : + ::Foam::simpleRegIOobject(Foam::debug::addOptimisationObject, name) + {} + + virtual ~addwriteNowSignalToOpt() = default; + + virtual void readData(Foam::Istream& is) + { + sigWriteNow::signal_ = readLabel(is); + sigWriteNow::set(true); + } + + virtual void writeData(Foam::Ostream& os) const + { + os << sigWriteNow::signal_; + } +}; + +addwriteNowSignalToOpt addwriteNowSignalToOpt_("writeNowSignal"); + +} // End namespace Foam + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::sigWriteNow::sigHandler(int) +{ + if (runTimePtr_) + { + Info<< "sigWriteNow :" + << " setting up write at end of the next iteration" << nl << endl; + runTimePtr_->writeOnce(); + } +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::sigWriteNow::sigWriteNow() +{} + + +Foam::sigWriteNow::sigWriteNow(Time& runTime, bool verbose) +{ + runTimePtr_ = &runTime; // Store runTime + set(verbose); +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::sigWriteNow::~sigWriteNow() +{ + if (!active()) + { + return; + } + + resetHandler("writeNow", signal_); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +bool Foam::sigWriteNow::active() +{ + return signal_ > 0; +} + + +int Foam::sigWriteNow::signalNumber() +{ + return signal_; +} + + +void Foam::sigWriteNow::set(bool verbose) +{ + if (!active()) + { + return; + } + + if (verbose) + { + Info<< "sigWriteNow :" + << " Enabling writing upon signal " << signal_ << nl; + } + + setHandler("writeNow", signal_, sigHandler); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/sigWriteNow.H b/src/OSspecific/MSwindows/signals/sigWriteNow.H new file mode 100644 index 00000000000..8ba2cedc89f --- /dev/null +++ b/src/OSspecific/MSwindows/signals/sigWriteNow.H @@ -0,0 +1,108 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2016-2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::sigWriteNow + +Description + Signal handler to write once and continue. + The interrupt is defined by OptimisationSwitches::writeNowSignal + +SourceFiles + sigWriteNow.C + +\*---------------------------------------------------------------------------*/ + +#ifndef sigWriteNow_H +#define sigWriteNow_H + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward Declarations +class Time; + +/*---------------------------------------------------------------------------*\ + Class sigWriteNow Declaration +\*---------------------------------------------------------------------------*/ + +class sigWriteNow +{ + // Private Data + + //- Signal number to use + static int signal_; + + + // Private Member Functions + + //- Handler for caught signals + static void sigHandler(int); + + +public: + + //- Allow setter access to signal_ + friend class addwriteNowSignalToOpt; + + + // Constructors + + //- Construct null + sigWriteNow(); + + //- Construct from components + sigWriteNow(Time& runTime, bool verbose=false); + + + //- Destructor + ~sigWriteNow(); + + + // Member Functions + + //- Is active? + static bool active(); + + //- The signal number being used + static int signalNumber(); + + //- Set/reset signal handler + static void set(bool verbose=false); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/signalMacros.C b/src/OSspecific/MSwindows/signals/signalMacros.C new file mode 100644 index 00000000000..8950ec7b309 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/signalMacros.C @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Description + File-local code for setting/resetting signal handlers. + +SourceFiles + signalMacros.C + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include <csignal> + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Saved old signal trapping setting (file-local variable) +static __p_sig_fn_t oldAction_ = SIG_DFL; + + +static void resetHandler(const char *what, int sigNum) +{ + const __p_sig_fn_t prev = ::signal(sigNum, oldAction_); + oldAction_ = SIG_DFL; + + if (SIG_ERR == prev) + { + FatalError + << "Cannot unset " << what << " signal (" << sigNum + << ") trapping" << endl + << abort(FatalError); + } +} + + +static void setHandler(const char *what, int sigNum, void (*handler)(int)) +{ + oldAction_ = ::signal(sigNum, handler); + + if (SIG_ERR == oldAction_) + { + FatalError + << "Could not set " << what << " signal (" << sigNum + << ") trapping" << endl + << abort(FatalError); + } +} + +} // End namespace Foam + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/timer.C b/src/OSspecific/MSwindows/signals/timer.C new file mode 100644 index 00000000000..36a0a2af616 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/timer.C @@ -0,0 +1,156 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2010, 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2016 OpenFOAM Foundation + | Copyright (C) 2011 Symscape +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +\*---------------------------------------------------------------------------*/ + +#include "timer.H" +#include "error.H" +#include "MSwindows.H" +#undef DebugInfo // Windows name clash with OpenFOAM messageStream + +#define WIN32_LEAN_AND_MEAN +#undef WINVER +#define WINVER 0x0500 // To access CreateTimerQueueTimer +#include <windows.h> + +// File-local functions +#include "signalMacros.C" + +#define SIGALRM 14 + + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ + defineTypeNameAndDebug(timer, 0); +} + +jmp_buf Foam::timer::envAlarm; + +unsigned int Foam::timer::oldTimeOut_ = 0; + +static HANDLE hTimer_ = nullptr; + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +static VOID CALLBACK timerExpired(PVOID lpParam, BOOLEAN TimerOrWaitFired) +{ + ::raise(SIGALRM); +} + + +// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // + +void Foam::timer::sigHandler(int) +{ + DebugInFunction << "Timed out. Jumping." << endl; + + longjmp(envAlarm, 1); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::timer::timer(unsigned int seconds) +: + timeOut_(seconds) +{ + if (!timeOut_) + { + return; + } + + // Singleton since handler is static function + if (hTimer_) + { + FatalErrorInFunction + << "timer already used." + << abort(FatalError); + } + + // Set alarm signal handler + setHandler("SIGALRM", SIGALRM, sigHandler); + + // Set alarm timer + const bool ok = ::CreateTimerQueueTimer + ( + &hTimer_, + nullptr, + static_cast<WAITORTIMERCALLBACK>(timerExpired), + nullptr, + timeOut_ * 1000, + 0, + 0 + ); + + if (!ok) + { + hTimer_ = nullptr; + FatalErrorInFunction + << "CreateTimerQueueTimer, " + << MSwindows::lastError() << nl + << abort(FatalError); + } + + DebugInFunction + << "Installing timeout " << int(timeOut_) << " seconds" + << " (overriding old timeout " << int(oldTimeOut_) << ")." << endl; +} + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::timer::~timer() +{ + if (!timeOut_) + { + return; + } + + DebugInFunction + << "timeOut=" << int(timeOut_) + << " : resetting timeOut to " << int(oldTimeOut_) << endl; + + // Reset alarm timer + const bool ok = ::DeleteTimerQueueTimer(nullptr, hTimer_, nullptr); + + hTimer_ = nullptr; + + if (!ok) + { + FatalErrorInFunction + << "DeleteTimerQueueTimer, " + << MSwindows::lastError() << nl + << abort(FatalError); + } + + resetHandler("SIGALRM", SIGALRM); +} + + +// ************************************************************************* // diff --git a/src/OSspecific/MSwindows/signals/timer.H b/src/OSspecific/MSwindows/signals/timer.H new file mode 100644 index 00000000000..823267bb5b9 --- /dev/null +++ b/src/OSspecific/MSwindows/signals/timer.H @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2004-2011, 2019 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- + | Copyright (C) 2011-2015 OpenFOAM Foundation +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. + +Class + Foam::timer + +Description + Implements a timeout mechanism via sigalarm. + + Example usage: + \code + timer myTimer(5); // 5 sec + .. + if (timedOut(myTimer)) + { + // timed out + } + else + { + // do something possible blocking + } + \endcode + + Constructor set signal handler on sigalarm and alarm(). Destructor + clears these. + +Warning + The setjmp restores complete register state so including local vars + held in regs. So if in blocking part something gets calced in a stack + based variable make sure it is declared 'volatile'. + +Note + timedOut is macro because setjmp can't be in member function of timer. + ?something to do with stack frames. + +SourceFiles + timer.C + +\*---------------------------------------------------------------------------*/ + +#ifndef timer_H +#define timer_H + +#include "className.H" +#include <csetjmp> + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Check if timeout has occurred +// keep setjmp in same stack frame so no function calls +#define timedOut(x) \ + ((x).timeOut_ ? setjmp(Foam::timer::envAlarm) : false) + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class timer Declaration +\*---------------------------------------------------------------------------*/ + +class timer +{ + // Private Data + + //- Old alarm() value + static unsigned int oldTimeOut_; + + + // Private Member Functions + + //- Alarm handler + static void sigHandler(int); + + +public: + + // Public Data + + //- Declare name of the class and its debug switch + ClassName("timer"); + + //- The time-out value (seconds). Needed by macro timedOut + unsigned int timeOut_; + + //- State for setjmp. Needed by macro timedOut + static jmp_buf envAlarm; + + + // Constructors + + //- Construct with specified time-out, a value of 0 makes it a no-op. + timer(unsigned int seconds); + + + //- Destructor. Restores the alarm and signal handler as required. + ~timer(); +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // -- GitLab