]> Git Repo - VerusCoin.git/blob - src/util.cpp
Clearly separate PUSHDATA and numeric argument MINIMALDATA tests
[VerusCoin.git] / src / util.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2014 The Bitcoin developers
3 // Distributed under the MIT/X11 software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5
6 #if defined(HAVE_CONFIG_H)
7 #include "config/bitcoin-config.h"
8 #endif
9
10 #include "util.h"
11
12 #include "chainparamsbase.h"
13 #include "random.h"
14 #include "serialize.h"
15 #include "sync.h"
16 #include "utilstrencodings.h"
17 #include "utiltime.h"
18
19 #include <stdarg.h>
20
21 #ifndef WIN32
22 // for posix_fallocate
23 #ifdef __linux__
24
25 #ifdef _POSIX_C_SOURCE
26 #undef _POSIX_C_SOURCE
27 #endif
28
29 #define _POSIX_C_SOURCE 200112L
30
31 #endif // __linux__
32
33 #include <algorithm>
34 #include <fcntl.h>
35 #include <sys/resource.h>
36 #include <sys/stat.h>
37
38 #else
39
40 #ifdef _MSC_VER
41 #pragma warning(disable:4786)
42 #pragma warning(disable:4804)
43 #pragma warning(disable:4805)
44 #pragma warning(disable:4717)
45 #endif
46
47 #ifdef _WIN32_WINNT
48 #undef _WIN32_WINNT
49 #endif
50 #define _WIN32_WINNT 0x0501
51
52 #ifdef _WIN32_IE
53 #undef _WIN32_IE
54 #endif
55 #define _WIN32_IE 0x0501
56
57 #define WIN32_LEAN_AND_MEAN 1
58 #ifndef NOMINMAX
59 #define NOMINMAX
60 #endif
61
62 #include <io.h> /* for _commit */
63 #include <shlobj.h>
64 #endif
65
66 #ifdef HAVE_SYS_PRCTL_H
67 #include <sys/prctl.h>
68 #endif
69
70 #include <boost/algorithm/string/case_conv.hpp> // for to_lower()
71 #include <boost/algorithm/string/join.hpp>
72 #include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
73 #include <boost/filesystem.hpp>
74 #include <boost/filesystem/fstream.hpp>
75 #include <boost/foreach.hpp>
76 #include <boost/program_options/detail/config_file.hpp>
77 #include <boost/program_options/parsers.hpp>
78 #include <boost/thread.hpp>
79 #include <openssl/crypto.h>
80 #include <openssl/rand.h>
81
82 // Work around clang compilation problem in Boost 1.46:
83 // /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
84 // See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
85 //           http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
86 namespace boost {
87
88     namespace program_options {
89         std::string to_internal(const std::string&);
90     }
91
92 } // namespace boost
93
94 using namespace std;
95
96 map<string, string> mapArgs;
97 map<string, vector<string> > mapMultiArgs;
98 bool fDebug = false;
99 bool fPrintToConsole = false;
100 bool fPrintToDebugLog = true;
101 bool fDaemon = false;
102 bool fServer = false;
103 string strMiscWarning;
104 bool fLogTimestamps = false;
105 bool fLogIPs = false;
106 volatile bool fReopenDebugLog = false;
107
108 // Init OpenSSL library multithreading support
109 static CCriticalSection** ppmutexOpenSSL;
110 void locking_callback(int mode, int i, const char* file, int line)
111 {
112     if (mode & CRYPTO_LOCK) {
113         ENTER_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
114     } else {
115         LEAVE_CRITICAL_SECTION(*ppmutexOpenSSL[i]);
116     }
117 }
118
119 // Init
120 class CInit
121 {
122 public:
123     CInit()
124     {
125         // Init OpenSSL library multithreading support
126         ppmutexOpenSSL = (CCriticalSection**)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(CCriticalSection*));
127         for (int i = 0; i < CRYPTO_num_locks(); i++)
128             ppmutexOpenSSL[i] = new CCriticalSection();
129         CRYPTO_set_locking_callback(locking_callback);
130
131 #ifdef WIN32
132         // Seed OpenSSL PRNG with current contents of the screen
133         RAND_screen();
134 #endif
135
136         // Seed OpenSSL PRNG with performance counter
137         RandAddSeed();
138     }
139     ~CInit()
140     {
141         // Securely erase the memory used by the PRNG
142         RAND_cleanup();
143         // Shutdown OpenSSL library multithreading support
144         CRYPTO_set_locking_callback(NULL);
145         for (int i = 0; i < CRYPTO_num_locks(); i++)
146             delete ppmutexOpenSSL[i];
147         OPENSSL_free(ppmutexOpenSSL);
148     }
149 }
150 instance_of_cinit;
151
152 // LogPrintf() has been broken a couple of times now
153 // by well-meaning people adding mutexes in the most straightforward way.
154 // It breaks because it may be called by global destructors during shutdown.
155 // Since the order of destruction of static/global objects is undefined,
156 // defining a mutex as a global object doesn't work (the mutex gets
157 // destroyed, and then some later destructor calls OutputDebugStringF,
158 // maybe indirectly, and you get a core dump at shutdown trying to lock
159 // the mutex).
160
161 static boost::once_flag debugPrintInitFlag = BOOST_ONCE_INIT;
162 // We use boost::call_once() to make sure these are initialized in
163 // in a thread-safe manner the first time it is called:
164 static FILE* fileout = NULL;
165 static boost::mutex* mutexDebugLog = NULL;
166
167 static void DebugPrintInit()
168 {
169     assert(fileout == NULL);
170     assert(mutexDebugLog == NULL);
171
172     boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
173     fileout = fopen(pathDebug.string().c_str(), "a");
174     if (fileout) setbuf(fileout, NULL); // unbuffered
175
176     mutexDebugLog = new boost::mutex();
177 }
178
179 bool LogAcceptCategory(const char* category)
180 {
181     if (category != NULL)
182     {
183         if (!fDebug)
184             return false;
185
186         // Give each thread quick access to -debug settings.
187         // This helps prevent issues debugging global destructors,
188         // where mapMultiArgs might be deleted before another
189         // global destructor calls LogPrint()
190         static boost::thread_specific_ptr<set<string> > ptrCategory;
191         if (ptrCategory.get() == NULL)
192         {
193             const vector<string>& categories = mapMultiArgs["-debug"];
194             ptrCategory.reset(new set<string>(categories.begin(), categories.end()));
195             // thread_specific_ptr automatically deletes the set when the thread ends.
196         }
197         const set<string>& setCategories = *ptrCategory.get();
198
199         // if not debugging everything and not debugging specific category, LogPrint does nothing.
200         if (setCategories.count(string("")) == 0 &&
201             setCategories.count(string(category)) == 0)
202             return false;
203     }
204     return true;
205 }
206
207 int LogPrintStr(const std::string &str)
208 {
209     int ret = 0; // Returns total number of characters written
210     if (fPrintToConsole)
211     {
212         // print to console
213         ret = fwrite(str.data(), 1, str.size(), stdout);
214         fflush(stdout);
215     }
216     else if (fPrintToDebugLog && AreBaseParamsConfigured())
217     {
218         static bool fStartedNewLine = true;
219         boost::call_once(&DebugPrintInit, debugPrintInitFlag);
220
221         if (fileout == NULL)
222             return ret;
223
224         boost::mutex::scoped_lock scoped_lock(*mutexDebugLog);
225
226         // reopen the log file, if requested
227         if (fReopenDebugLog) {
228             fReopenDebugLog = false;
229             boost::filesystem::path pathDebug = GetDataDir() / "debug.log";
230             if (freopen(pathDebug.string().c_str(),"a",fileout) != NULL)
231                 setbuf(fileout, NULL); // unbuffered
232         }
233
234         // Debug print useful for profiling
235         if (fLogTimestamps && fStartedNewLine)
236             ret += fprintf(fileout, "%s ", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()).c_str());
237         if (!str.empty() && str[str.size()-1] == '\n')
238             fStartedNewLine = true;
239         else
240             fStartedNewLine = false;
241
242         ret = fwrite(str.data(), 1, str.size(), fileout);
243     }
244
245     return ret;
246 }
247
248 static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
249 {
250     // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
251     if (name.find("-no") == 0)
252     {
253         std::string positive("-");
254         positive.append(name.begin()+3, name.end());
255         if (mapSettingsRet.count(positive) == 0)
256         {
257             bool value = !GetBoolArg(name, false);
258             mapSettingsRet[positive] = (value ? "1" : "0");
259         }
260     }
261 }
262
263 void ParseParameters(int argc, const char* const argv[])
264 {
265     mapArgs.clear();
266     mapMultiArgs.clear();
267
268     for (int i = 1; i < argc; i++)
269     {
270         std::string str(argv[i]);
271         std::string strValue;
272         size_t is_index = str.find('=');
273         if (is_index != std::string::npos)
274         {
275             strValue = str.substr(is_index+1);
276             str = str.substr(0, is_index);
277         }
278 #ifdef WIN32
279         boost::to_lower(str);
280         if (boost::algorithm::starts_with(str, "/"))
281             str = "-" + str.substr(1);
282 #endif
283
284         if (str[0] != '-')
285             break;
286
287         // Interpret --foo as -foo.
288         // If both --foo and -foo are set, the last takes effect.
289         if (str.length() > 1 && str[1] == '-')
290             str = str.substr(1);
291
292         mapArgs[str] = strValue;
293         mapMultiArgs[str].push_back(strValue);
294     }
295
296     // New 0.6 features:
297     BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
298     {
299         // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
300         InterpretNegativeSetting(entry.first, mapArgs);
301     }
302 }
303
304 std::string GetArg(const std::string& strArg, const std::string& strDefault)
305 {
306     if (mapArgs.count(strArg))
307         return mapArgs[strArg];
308     return strDefault;
309 }
310
311 int64_t GetArg(const std::string& strArg, int64_t nDefault)
312 {
313     if (mapArgs.count(strArg))
314         return atoi64(mapArgs[strArg]);
315     return nDefault;
316 }
317
318 bool GetBoolArg(const std::string& strArg, bool fDefault)
319 {
320     if (mapArgs.count(strArg))
321     {
322         if (mapArgs[strArg].empty())
323             return true;
324         return (atoi(mapArgs[strArg]) != 0);
325     }
326     return fDefault;
327 }
328
329 bool SoftSetArg(const std::string& strArg, const std::string& strValue)
330 {
331     if (mapArgs.count(strArg))
332         return false;
333     mapArgs[strArg] = strValue;
334     return true;
335 }
336
337 bool SoftSetBoolArg(const std::string& strArg, bool fValue)
338 {
339     if (fValue)
340         return SoftSetArg(strArg, std::string("1"));
341     else
342         return SoftSetArg(strArg, std::string("0"));
343 }
344
345 static std::string FormatException(std::exception* pex, const char* pszThread)
346 {
347 #ifdef WIN32
348     char pszModule[MAX_PATH] = "";
349     GetModuleFileNameA(NULL, pszModule, sizeof(pszModule));
350 #else
351     const char* pszModule = "bitcoin";
352 #endif
353     if (pex)
354         return strprintf(
355             "EXCEPTION: %s       \n%s       \n%s in %s       \n", typeid(*pex).name(), pex->what(), pszModule, pszThread);
356     else
357         return strprintf(
358             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
359 }
360
361 void PrintExceptionContinue(std::exception* pex, const char* pszThread)
362 {
363     std::string message = FormatException(pex, pszThread);
364     LogPrintf("\n\n************************\n%s\n", message);
365     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
366     strMiscWarning = message;
367 }
368
369 boost::filesystem::path GetDefaultDataDir()
370 {
371     namespace fs = boost::filesystem;
372     // Windows < Vista: C:\Documents and Settings\Username\Application Data\Bitcoin
373     // Windows >= Vista: C:\Users\Username\AppData\Roaming\Bitcoin
374     // Mac: ~/Library/Application Support/Bitcoin
375     // Unix: ~/.bitcoin
376 #ifdef WIN32
377     // Windows
378     return GetSpecialFolderPath(CSIDL_APPDATA) / "Bitcoin";
379 #else
380     fs::path pathRet;
381     char* pszHome = getenv("HOME");
382     if (pszHome == NULL || strlen(pszHome) == 0)
383         pathRet = fs::path("/");
384     else
385         pathRet = fs::path(pszHome);
386 #ifdef MAC_OSX
387     // Mac
388     pathRet /= "Library/Application Support";
389     TryCreateDirectory(pathRet);
390     return pathRet / "Bitcoin";
391 #else
392     // Unix
393     return pathRet / ".bitcoin";
394 #endif
395 #endif
396 }
397
398 static boost::filesystem::path pathCached;
399 static boost::filesystem::path pathCachedNetSpecific;
400 static CCriticalSection csPathCached;
401
402 const boost::filesystem::path &GetDataDir(bool fNetSpecific)
403 {
404     namespace fs = boost::filesystem;
405
406     LOCK(csPathCached);
407
408     fs::path &path = fNetSpecific ? pathCachedNetSpecific : pathCached;
409
410     // This can be called during exceptions by LogPrintf(), so we cache the
411     // value so we don't have to do memory allocations after that.
412     if (!path.empty())
413         return path;
414
415     if (mapArgs.count("-datadir")) {
416         path = fs::system_complete(mapArgs["-datadir"]);
417         if (!fs::is_directory(path)) {
418             path = "";
419             return path;
420         }
421     } else {
422         path = GetDefaultDataDir();
423     }
424     if (fNetSpecific)
425         path /= BaseParams().DataDir();
426
427     fs::create_directories(path);
428
429     return path;
430 }
431
432 void ClearDatadirCache()
433 {
434     pathCached = boost::filesystem::path();
435     pathCachedNetSpecific = boost::filesystem::path();
436 }
437
438 boost::filesystem::path GetConfigFile()
439 {
440     boost::filesystem::path pathConfigFile(GetArg("-conf", "bitcoin.conf"));
441     if (!pathConfigFile.is_complete())
442         pathConfigFile = GetDataDir(false) / pathConfigFile;
443
444     return pathConfigFile;
445 }
446
447 void ReadConfigFile(map<string, string>& mapSettingsRet,
448                     map<string, vector<string> >& mapMultiSettingsRet)
449 {
450     boost::filesystem::ifstream streamConfig(GetConfigFile());
451     if (!streamConfig.good())
452         return; // No bitcoin.conf file is OK
453
454     set<string> setOptions;
455     setOptions.insert("*");
456
457     for (boost::program_options::detail::config_file_iterator it(streamConfig, setOptions), end; it != end; ++it)
458     {
459         // Don't overwrite existing settings so command line settings override bitcoin.conf
460         string strKey = string("-") + it->string_key;
461         if (mapSettingsRet.count(strKey) == 0)
462         {
463             mapSettingsRet[strKey] = it->value[0];
464             // interpret nofoo=1 as foo=0 (and nofoo=0 as foo=1) as long as foo not set)
465             InterpretNegativeSetting(strKey, mapSettingsRet);
466         }
467         mapMultiSettingsRet[strKey].push_back(it->value[0]);
468     }
469     // If datadir is changed in .conf file:
470     ClearDatadirCache();
471 }
472
473 #ifndef WIN32
474 boost::filesystem::path GetPidFile()
475 {
476     boost::filesystem::path pathPidFile(GetArg("-pid", "bitcoind.pid"));
477     if (!pathPidFile.is_complete()) pathPidFile = GetDataDir() / pathPidFile;
478     return pathPidFile;
479 }
480
481 void CreatePidFile(const boost::filesystem::path &path, pid_t pid)
482 {
483     FILE* file = fopen(path.string().c_str(), "w");
484     if (file)
485     {
486         fprintf(file, "%d\n", pid);
487         fclose(file);
488     }
489 }
490 #endif
491
492 bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
493 {
494 #ifdef WIN32
495     return MoveFileExA(src.string().c_str(), dest.string().c_str(),
496                        MOVEFILE_REPLACE_EXISTING) != 0;
497 #else
498     int rc = std::rename(src.string().c_str(), dest.string().c_str());
499     return (rc == 0);
500 #endif /* WIN32 */
501 }
502
503 // Ignores exceptions thrown by Boost's create_directory if the requested directory exists.
504 // Specifically handles case where path p exists, but it wasn't possible for the user to
505 // write to the parent directory.
506 bool TryCreateDirectory(const boost::filesystem::path& p)
507 {
508     try
509     {
510         return boost::filesystem::create_directory(p);
511     } catch (boost::filesystem::filesystem_error) {
512         if (!boost::filesystem::exists(p) || !boost::filesystem::is_directory(p))
513             throw;
514     }
515
516     // create_directory didn't create the directory, it had to have existed already
517     return false;
518 }
519
520 void FileCommit(FILE *fileout)
521 {
522     fflush(fileout); // harmless if redundantly called
523 #ifdef WIN32
524     HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(fileout));
525     FlushFileBuffers(hFile);
526 #else
527     #if defined(__linux__) || defined(__NetBSD__)
528     fdatasync(fileno(fileout));
529     #elif defined(__APPLE__) && defined(F_FULLFSYNC)
530     fcntl(fileno(fileout), F_FULLFSYNC, 0);
531     #else
532     fsync(fileno(fileout));
533     #endif
534 #endif
535 }
536
537 bool TruncateFile(FILE *file, unsigned int length) {
538 #if defined(WIN32)
539     return _chsize(_fileno(file), length) == 0;
540 #else
541     return ftruncate(fileno(file), length) == 0;
542 #endif
543 }
544
545 // this function tries to raise the file descriptor limit to the requested number.
546 // It returns the actual file descriptor limit (which may be more or less than nMinFD)
547 int RaiseFileDescriptorLimit(int nMinFD) {
548 #if defined(WIN32)
549     return 2048;
550 #else
551     struct rlimit limitFD;
552     if (getrlimit(RLIMIT_NOFILE, &limitFD) != -1) {
553         if (limitFD.rlim_cur < (rlim_t)nMinFD) {
554             limitFD.rlim_cur = nMinFD;
555             if (limitFD.rlim_cur > limitFD.rlim_max)
556                 limitFD.rlim_cur = limitFD.rlim_max;
557             setrlimit(RLIMIT_NOFILE, &limitFD);
558             getrlimit(RLIMIT_NOFILE, &limitFD);
559         }
560         return limitFD.rlim_cur;
561     }
562     return nMinFD; // getrlimit failed, assume it's fine
563 #endif
564 }
565
566 // this function tries to make a particular range of a file allocated (corresponding to disk space)
567 // it is advisory, and the range specified in the arguments will never contain live data
568 void AllocateFileRange(FILE *file, unsigned int offset, unsigned int length) {
569 #if defined(WIN32)
570     // Windows-specific version
571     HANDLE hFile = (HANDLE)_get_osfhandle(_fileno(file));
572     LARGE_INTEGER nFileSize;
573     int64_t nEndPos = (int64_t)offset + length;
574     nFileSize.u.LowPart = nEndPos & 0xFFFFFFFF;
575     nFileSize.u.HighPart = nEndPos >> 32;
576     SetFilePointerEx(hFile, nFileSize, 0, FILE_BEGIN);
577     SetEndOfFile(hFile);
578 #elif defined(MAC_OSX)
579     // OSX specific version
580     fstore_t fst;
581     fst.fst_flags = F_ALLOCATECONTIG;
582     fst.fst_posmode = F_PEOFPOSMODE;
583     fst.fst_offset = 0;
584     fst.fst_length = (off_t)offset + length;
585     fst.fst_bytesalloc = 0;
586     if (fcntl(fileno(file), F_PREALLOCATE, &fst) == -1) {
587         fst.fst_flags = F_ALLOCATEALL;
588         fcntl(fileno(file), F_PREALLOCATE, &fst);
589     }
590     ftruncate(fileno(file), fst.fst_length);
591 #elif defined(__linux__)
592     // Version using posix_fallocate
593     off_t nEndPos = (off_t)offset + length;
594     posix_fallocate(fileno(file), 0, nEndPos);
595 #else
596     // Fallback version
597     // TODO: just write one byte per block
598     static const char buf[65536] = {};
599     fseek(file, offset, SEEK_SET);
600     while (length > 0) {
601         unsigned int now = 65536;
602         if (length < now)
603             now = length;
604         fwrite(buf, 1, now, file); // allowed to fail; this function is advisory anyway
605         length -= now;
606     }
607 #endif
608 }
609
610 void ShrinkDebugFile()
611 {
612     // Scroll debug.log if it's getting too big
613     boost::filesystem::path pathLog = GetDataDir() / "debug.log";
614     FILE* file = fopen(pathLog.string().c_str(), "r");
615     if (file && boost::filesystem::file_size(pathLog) > 10 * 1000000)
616     {
617         // Restart the file with some of the end
618         std::vector <char> vch(200000,0);
619         fseek(file, -((long)vch.size()), SEEK_END);
620         int nBytes = fread(begin_ptr(vch), 1, vch.size(), file);
621         fclose(file);
622
623         file = fopen(pathLog.string().c_str(), "w");
624         if (file)
625         {
626             fwrite(begin_ptr(vch), 1, nBytes, file);
627             fclose(file);
628         }
629     }
630     else if (file != NULL)
631         fclose(file);
632 }
633
634 #ifdef WIN32
635 boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
636 {
637     namespace fs = boost::filesystem;
638
639     char pszPath[MAX_PATH] = "";
640
641     if(SHGetSpecialFolderPathA(NULL, pszPath, nFolder, fCreate))
642     {
643         return fs::path(pszPath);
644     }
645
646     LogPrintf("SHGetSpecialFolderPathA() failed, could not obtain requested path.\n");
647     return fs::path("");
648 }
649 #endif
650
651 boost::filesystem::path GetTempPath() {
652 #if BOOST_FILESYSTEM_VERSION == 3
653     return boost::filesystem::temp_directory_path();
654 #else
655     // TODO: remove when we don't support filesystem v2 anymore
656     boost::filesystem::path path;
657 #ifdef WIN32
658     char pszPath[MAX_PATH] = "";
659
660     if (GetTempPathA(MAX_PATH, pszPath))
661         path = boost::filesystem::path(pszPath);
662 #else
663     path = boost::filesystem::path("/tmp");
664 #endif
665     if (path.empty() || !boost::filesystem::is_directory(path)) {
666         LogPrintf("GetTempPath(): failed to find temp path\n");
667         return boost::filesystem::path("");
668     }
669     return path;
670 #endif
671 }
672
673 void runCommand(std::string strCommand)
674 {
675     int nErr = ::system(strCommand.c_str());
676     if (nErr)
677         LogPrintf("runCommand error: system(%s) returned %d\n", strCommand, nErr);
678 }
679
680 void RenameThread(const char* name)
681 {
682 #if defined(PR_SET_NAME)
683     // Only the first 15 characters are used (16 - NUL terminator)
684     ::prctl(PR_SET_NAME, name, 0, 0, 0);
685 #elif 0 && (defined(__FreeBSD__) || defined(__OpenBSD__))
686     // TODO: This is currently disabled because it needs to be verified to work
687     //       on FreeBSD or OpenBSD first. When verified the '0 &&' part can be
688     //       removed.
689     pthread_set_name_np(pthread_self(), name);
690
691 #elif defined(MAC_OSX) && defined(__MAC_OS_X_VERSION_MAX_ALLOWED)
692
693 // pthread_setname_np is XCode 10.6-and-later
694 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
695     pthread_setname_np(name);
696 #endif
697
698 #else
699     // Prevent warnings for unused parameters...
700     (void)name;
701 #endif
702 }
703
704 void SetupEnvironment()
705 {
706 #ifndef WIN32
707     try
708     {
709 #if BOOST_FILESYSTEM_VERSION == 3
710             boost::filesystem::path::codecvt(); // Raises runtime error if current locale is invalid
711 #else // boost filesystem v2
712             std::locale();                      // Raises runtime error if current locale is invalid
713 #endif
714     } catch(std::runtime_error &e)
715     {
716         setenv("LC_ALL", "C", 1); // Force C locale
717     }
718 #endif
719 }
720
721 void SetThreadPriority(int nPriority)
722 {
723 #ifdef WIN32
724     SetThreadPriority(GetCurrentThread(), nPriority);
725 #else // WIN32
726 #ifdef PRIO_THREAD
727     setpriority(PRIO_THREAD, 0, nPriority);
728 #else // PRIO_THREAD
729     setpriority(PRIO_PROCESS, 0, nPriority);
730 #endif // PRIO_THREAD
731 #endif // WIN32
732 }
This page took 0.063212 seconds and 4 git commands to generate.