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