From 0184a841d3914bb78c7c6fa87ce9da86a2d5992a Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 11:17:50 +0000 Subject: Begin sketching out the process interface. The coding style used here is not LLVM's style because this is modeled after a Boost interface and thus done in the style of a candidate C++ standard library interface. I'll probably end up proposing it as a standard C++ library if it proves to be reasonably portable and useful. This is just the most basic parts of the interface -- getting the process ID out of it. However, it helps sketch out some of the boiler plate such as the base class, derived class, shared code, and static factory function. It also introduces a unittest so that I can incrementally ensure this stuff works. However, I've not even compiled this code for Windows yet. I'll try to fix any Windows fallout from the bots, and if I can't fix it I'll revert and get someone on Windows to help out. There isn't a lot more that is mandatory, so soon I'll switch to just stubbing out the Windows side and get Michael Spencer to help with implementation as he can test it directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171289 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index 5204147ce3..dedc4430d6 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -44,6 +44,12 @@ using namespace llvm; using namespace sys; + +process::id_type self_process::get_id() { + return getpid(); +} + + unsigned Process::GetPageSize() { -- cgit v1.2.3-18-g5258 From 9b4aba85a89f9347212e00f80953f2a685ffeb36 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 11:45:20 +0000 Subject: Switch this code to a more idiomatic double using namespace directive. Fix a truly odd namespace qualifier that was flat out wrong in the process. The fully qualified namespace would have been llvm::sys::TimeValue, llvm::TimeValue makes no sense. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171292 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index dedc4430d6..b83f5079ce 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -324,7 +324,7 @@ static unsigned GetRandomNumberSeed() { // Otherwise, swizzle the current time and the process ID to form a reasonable // seed. - TimeValue Now = llvm::TimeValue::now(); + TimeValue Now = TimeValue::now(); return hash_combine(Now.seconds(), Now.nanoseconds(), ::getpid()); } #endif -- cgit v1.2.3-18-g5258 From e0e1985b3b71f21cd1d6c1e4924abf0f5b499a73 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 22:17:59 +0000 Subject: Remove an unused function in the old Process interface. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171327 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index b83f5079ce..e96d37ce56 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -92,26 +92,6 @@ size_t Process::GetMallocUsage() { #endif } -size_t -Process::GetTotalMemoryUsage() -{ -#if defined(HAVE_MALLINFO) - struct mallinfo mi = ::mallinfo(); - return mi.uordblks + mi.hblkhd; -#elif defined(HAVE_MALLOC_ZONE_STATISTICS) && defined(HAVE_MALLOC_MALLOC_H) - malloc_statistics_t Stats; - malloc_zone_statistics(malloc_default_zone(), &Stats); - return Stats.size_allocated; // darwin -#elif defined(HAVE_GETRUSAGE) && !defined(__HAIKU__) - struct rusage usage; - ::getrusage(RUSAGE_SELF, &usage); - return usage.ru_maxrss; -#else -#warning Cannot get total memory size on this platform - return 0; -#endif -} - void Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, TimeValue& sys_time) -- cgit v1.2.3-18-g5258 From 814afe91ccad0e5e1f767303d780fa0318fa5212 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 23:23:35 +0000 Subject: Flesh out a page size accessor in the new API. Implement the old API in terms of the new one. This simplifies the implementation on Windows which can now re-use the self_process's once initialization. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171330 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index e96d37ce56..9ad6272bab 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -49,10 +49,7 @@ process::id_type self_process::get_id() { return getpid(); } - -unsigned -Process::GetPageSize() -{ +static unsigned getPageSize() { #if defined(__CYGWIN__) // On Cygwin, getpagesize() returns 64k but the page size for the purposes of // memory protection and mmap() is 4k. @@ -68,6 +65,12 @@ Process::GetPageSize() return static_cast(page_size); } +// This constructor guaranteed to be run exactly once on a single thread, and +// sets up various process invariants that can be queried cheaply from then on. +self_process::self_process() : PageSize(getPageSize()) { +} + + size_t Process::GetMallocUsage() { #if defined(HAVE_MALLINFO) struct mallinfo mi; -- cgit v1.2.3-18-g5258 From f5867ab7178784bc63a3deafcf4fb09260e4d19a Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 23:31:56 +0000 Subject: Go ahead and get rid of the old page size interface and convert all the users over to the new one. No sense maintaining this "compatibility" layer it seems. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171331 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Memory.inc | 16 ++++++++-------- lib/Support/Unix/PathV2.inc | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Memory.inc b/lib/Support/Unix/Memory.inc index 9a8abd27f1..40d6b3fefd 100644 --- a/lib/Support/Unix/Memory.inc +++ b/lib/Support/Unix/Memory.inc @@ -73,7 +73,7 @@ Memory::allocateMappedMemory(size_t NumBytes, if (NumBytes == 0) return MemoryBlock(); - static const size_t PageSize = Process::GetPageSize(); + static const size_t PageSize = process::get_self()->page_size(); const size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; @@ -166,8 +166,8 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, std::string *ErrMsg) { if (NumBytes == 0) return MemoryBlock(); - size_t pageSize = Process::GetPageSize(); - size_t NumPages = (NumBytes+pageSize-1)/pageSize; + size_t PageSize = process::get_self()->page_size(); + size_t NumPages = (NumBytes+PageSize-1)/PageSize; int fd = -1; #ifdef NEED_DEV_ZERO_FOR_MMAP @@ -191,10 +191,10 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, NearBlock->size() : 0; #if defined(__APPLE__) && defined(__arm__) - void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_EXEC, + void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_EXEC, flags, fd, 0); #else - void *pa = ::mmap(start, pageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, + void *pa = ::mmap(start, PageSize*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC, flags, fd, 0); #endif if (pa == MAP_FAILED) { @@ -207,7 +207,7 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, #if defined(__APPLE__) && defined(__arm__) kern_return_t kr = vm_protect(mach_task_self(), (vm_address_t)pa, - (vm_size_t)(pageSize*NumPages), 0, + (vm_size_t)(PageSize*NumPages), 0, VM_PROT_READ | VM_PROT_EXECUTE | VM_PROT_COPY); if (KERN_SUCCESS != kr) { MakeErrMsg(ErrMsg, "vm_protect max RX failed"); @@ -215,7 +215,7 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, } kr = vm_protect(mach_task_self(), (vm_address_t)pa, - (vm_size_t)(pageSize*NumPages), 0, + (vm_size_t)(PageSize*NumPages), 0, VM_PROT_READ | VM_PROT_WRITE); if (KERN_SUCCESS != kr) { MakeErrMsg(ErrMsg, "vm_protect RW failed"); @@ -225,7 +225,7 @@ Memory::AllocateRWX(size_t NumBytes, const MemoryBlock* NearBlock, MemoryBlock result; result.Address = pa; - result.Size = NumPages*pageSize; + result.Size = NumPages*PageSize; return result; } diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index 453267046a..25712a8a9f 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -575,7 +575,7 @@ const char *mapped_file_region::const_data() const { } int mapped_file_region::alignment() { - return Process::GetPageSize(); + return process::get_self()->page_size(); } error_code detail::directory_iterator_construct(detail::DirIterState &it, -- cgit v1.2.3-18-g5258 From 2bbe46647555cdd05fe0db5f1dd2839330a647b2 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 23:38:28 +0000 Subject: Remove an unused method on the Program class. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171332 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Program.inc | 5 ----- 1 file changed, 5 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index bd75046aa9..aac52414f1 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -47,11 +47,6 @@ Program::Program() : Data_(0) {} Program::~Program() {} -unsigned Program::GetPid() const { - uint64_t pid = reinterpret_cast(Data_); - return static_cast(pid); -} - // This function just uses the PATH environment variable to find the program. Path Program::FindProgramByName(const std::string& progName) { -- cgit v1.2.3-18-g5258 From a0d8f28a9cbebfd3ddb32dfe3e0a286ede1678c5 Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Mon, 31 Dec 2012 23:44:47 +0000 Subject: Remove an unused method on Program. I'm simplifying this interface as much as I can before merging it with the new process interface. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171334 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Program.inc | 18 ------------------ 1 file changed, 18 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Program.inc b/lib/Support/Unix/Program.inc index aac52414f1..c384316e20 100644 --- a/lib/Support/Unix/Program.inc +++ b/lib/Support/Unix/Program.inc @@ -389,24 +389,6 @@ Program::Wait(const sys::Path &path, #endif } -bool -Program::Kill(std::string* ErrMsg) { - if (Data_ == 0) { - MakeErrMsg(ErrMsg, "Process not started!"); - return true; - } - - uint64_t pid64 = reinterpret_cast(Data_); - pid_t pid = static_cast(pid64); - - if (kill(pid, SIGKILL) != 0) { - MakeErrMsg(ErrMsg, "The process couldn't be killed!"); - return true; - } - - return false; -} - error_code Program::ChangeStdinToBinary(){ // Do nothing, as Unix doesn't differentiate between text and binary. return make_error_code(errc::success); -- cgit v1.2.3-18-g5258 From 73c35d86b9d5236be5b3f49bc8df11008b96636e Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Fri, 4 Jan 2013 23:19:55 +0000 Subject: Add time getters to the process interface for requesting the elapsed wall time, user time, and system time since a process started. For walltime, we currently use TimeValue's interface and a global initializer to compute a close approximation of total process runtime. For user time, this adds support for an somewhat more precise timing mechanism -- clock_gettime with the CLOCK_PROCESS_CPUTIME_ID clock selected. For system time, we have to do a full getrusage call to extract the system time from the OS. This is expensive but unavoidable. In passing, clean up the implementation of the old APIs and fix some latent bugs in the Windows code. This might have manifested on Windows ARM systems or other systems with strange 64-bit integer behavior. The old API for this both user time and system time simultaneously from a single getrusage call. While this results in fewer system calls, it also results in a lower precision user time and if only user time is desired, it introduces a higher overhead. It may be worthwhile to switch some of the pass timers to not track system time and directly track user and wall time. The old API also tracked walltime in a confusing way -- it just set it to the current walltime rather than providing any measure of wall time since the process started the way buth user and system time are tracked. The new API is more consistent here. The plan is to eventually implement these methods for a *child* process by using the wait3(2) system call to populate an rusage struct representing the whole subprocess execution. That way, after waiting on a child process its stats will become accurate and cheap to query. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171551 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 62 ++++++++++++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 22 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index 9ad6272bab..a525538f78 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -49,6 +49,43 @@ process::id_type self_process::get_id() { return getpid(); } +static std::pair getRUsageTimes() { +#if defined(HAVE_GETRUSAGE) + struct rusage RU; + ::getrusage(RUSAGE_SELF, &RU); + return std::make_pair( + TimeValue( + static_cast(RU.ru_utime.tv_sec), + static_cast( + RU.ru_utime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND)), + TimeValue( + static_cast(RU.ru_stime.tv_sec), + static_cast( + RU.ru_stime.tv_usec * TimeValue::NANOSECONDS_PER_MICROSECOND))); +#else +#warning Cannot get usage times on this platform + return std::make_pair(TimeValue(), TimeValue()); +#endif +} + +TimeValue self_process::get_user_time() const { +#ifdef _POSIX_CPUTIME + // Try to get a high resolution CPU timer. + struct timespec TS; + if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0) + return TimeValue(static_cast(TS.tv_sec), + static_cast(TS.tv_nsec)); +#endif + + // Otherwise fall back to rusage based timing. + return getRUsageTimes().first; +} + +TimeValue self_process::get_system_time() const { + // We can only collect system time by inspecting the results of getrusage. + return getRUsageTimes().second; +} + static unsigned getPageSize() { #if defined(__CYGWIN__) // On Cygwin, getpagesize() returns 64k but the page size for the purposes of @@ -95,29 +132,10 @@ size_t Process::GetMallocUsage() { #endif } -void -Process::GetTimeUsage(TimeValue& elapsed, TimeValue& user_time, - TimeValue& sys_time) -{ +void Process::GetTimeUsage(TimeValue &elapsed, TimeValue &user_time, + TimeValue &sys_time) { elapsed = TimeValue::now(); -#if defined(HAVE_GETRUSAGE) - struct rusage usage; - ::getrusage(RUSAGE_SELF, &usage); - user_time = TimeValue( - static_cast( usage.ru_utime.tv_sec ), - static_cast( usage.ru_utime.tv_usec * - TimeValue::NANOSECONDS_PER_MICROSECOND ) ); - sys_time = TimeValue( - static_cast( usage.ru_stime.tv_sec ), - static_cast( usage.ru_stime.tv_usec * - TimeValue::NANOSECONDS_PER_MICROSECOND ) ); -#else -#warning Cannot get usage times on this platform - user_time.seconds(0); - user_time.microseconds(0); - sys_time.seconds(0); - sys_time.microseconds(0); -#endif + llvm::tie(user_time, sys_time) = getRUsageTimes(); } int Process::GetCurrentUserId() { -- cgit v1.2.3-18-g5258 From 4cff412ecc4c760f0bbade18da02169967dc5ccf Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 5 Jan 2013 00:11:21 +0000 Subject: Try to suppress the use of clock_gettime on Darwin which apparantly defines _POSIX_CPUTIME but doesn't support the clock_* functions. I don't test the value of _POSIX_CPUTIME because the spec merely says that if it is defined, the CPU-specific timers are available, whereas it says that _POSIX_TIMERS must be defined and defined to a value greater than zero. However, this may not work, as the POSIX spec clearly states: "If the symbolic constant _POSIX_CPUTIME is defined, then the symbolic constant _POSIX_TIMERS shall also be defined by the implementation to have the value 200112L." If this doesn't work, I'll add more hacks for Darwin. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171565 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index a525538f78..c6dd3c0dc5 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -69,7 +69,7 @@ static std::pair getRUsageTimes() { } TimeValue self_process::get_user_time() const { -#ifdef _POSIX_CPUTIME +#if _POSIX_TIMERS > 0 && defined(_POSIX_CPUTIME) // Try to get a high resolution CPU timer. struct timespec TS; if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0) -- cgit v1.2.3-18-g5258 From 6a40db40eea4f3103cc05610949f5fe217739eea Mon Sep 17 00:00:00 2001 From: Chandler Carruth Date: Sat, 5 Jan 2013 00:42:50 +0000 Subject: Eric thought that Darwin was right to use -1 consistently rather than leaving this undefined, and despite the sentence in the standard that seems to require it, I'll cede the point and assume its a bug in the wording. Other parts of POSIX regularly allow for things to be -1 instead of undefined, this should too. Makes things more consistent too. This should have to real impact for folks though. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171574 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Process.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Process.inc b/lib/Support/Unix/Process.inc index c6dd3c0dc5..1335b78e86 100644 --- a/lib/Support/Unix/Process.inc +++ b/lib/Support/Unix/Process.inc @@ -69,7 +69,7 @@ static std::pair getRUsageTimes() { } TimeValue self_process::get_user_time() const { -#if _POSIX_TIMERS > 0 && defined(_POSIX_CPUTIME) +#if _POSIX_TIMERS > 0 && _POSIX_CPUTIME > 0 // Try to get a high resolution CPU timer. struct timespec TS; if (::clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &TS) == 0) -- cgit v1.2.3-18-g5258 From f48acd5ecd2616623f441f2922d8b4c637e3cd6c Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Wed, 9 Jan 2013 19:42:40 +0000 Subject: Move the internal PrintStackTrace function that is used for llvm::sys::PrintStackTraceOnErrorSignal(), into a new function llvm::sys::PrintStackTrace, so that it's available to clients for logging purposes. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171989 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/Signals.inc | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/Signals.inc b/lib/Support/Unix/Signals.inc index 9e98af7368..87162d6951 100644 --- a/lib/Support/Unix/Signals.inc +++ b/lib/Support/Unix/Signals.inc @@ -254,7 +254,7 @@ void llvm::sys::AddSignalHandler(void (*FnPtr)(void *), void *Cookie) { // // On glibc systems we have the 'backtrace' function, which works nicely, but // doesn't demangle symbols. -static void PrintStackTrace(void *) { +void llvm::sys::PrintStackTrace(FILE *FD) { #if defined(HAVE_BACKTRACE) && defined(ENABLE_BACKTRACES) static void* StackTrace[256]; // Use backtrace() to output a backtrace on Linux systems with glibc. @@ -278,26 +278,26 @@ static void PrintStackTrace(void *) { Dl_info dlinfo; dladdr(StackTrace[i], &dlinfo); - fprintf(stderr, "%-2d", i); + fprintf(FD, "%-2d", i); const char* name = strrchr(dlinfo.dli_fname, '/'); - if (name == NULL) fprintf(stderr, " %-*s", width, dlinfo.dli_fname); - else fprintf(stderr, " %-*s", width, name+1); + if (name == NULL) fprintf(FD, " %-*s", width, dlinfo.dli_fname); + else fprintf(FD, " %-*s", width, name+1); - fprintf(stderr, " %#0*lx", + fprintf(FD, " %#0*lx", (int)(sizeof(void*) * 2) + 2, (unsigned long)StackTrace[i]); if (dlinfo.dli_sname != NULL) { int res; - fputc(' ', stderr); + fputc(' ', FD); char* d = abi::__cxa_demangle(dlinfo.dli_sname, NULL, NULL, &res); - if (d == NULL) fputs(dlinfo.dli_sname, stderr); - else fputs(d, stderr); + if (d == NULL) fputs(dlinfo.dli_sname, FD); + else fputs(d, FD); free(d); - fprintf(stderr, " + %tu",(char*)StackTrace[i]-(char*)dlinfo.dli_saddr); + fprintf(FD, " + %tu",(char*)StackTrace[i]-(char*)dlinfo.dli_saddr); } - fputc('\n', stderr); + fputc('\n', FD); } #else backtrace_symbols_fd(StackTrace, depth, STDERR_FILENO); @@ -305,10 +305,14 @@ static void PrintStackTrace(void *) { #endif } +static void PrintStackTraceSignalHandler(void *) { + PrintStackTrace(stderr); +} + /// PrintStackTraceOnErrorSignal - When an error signal (such as SIGABRT or /// SIGSEGV) is delivered to the process, print a stack trace and then exit. void llvm::sys::PrintStackTraceOnErrorSignal() { - AddSignalHandler(PrintStackTrace, 0); + AddSignalHandler(PrintStackTraceSignalHandler, 0); #if defined(__APPLE__) // Environment variable to disable any kind of crash dialog. -- cgit v1.2.3-18-g5258 From 06c7008e30d3e278f2d779135ff2ce50bfc643fc Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 10 Jan 2013 01:58:46 +0000 Subject: Fix a race condition in llvm::sys::path::unique_file: when we end up failing to create the unique file because the path doesn't exist, don't fail if someone else manages to create the path before we do. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@172032 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Unix/PathV2.inc | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'lib/Support/Unix') diff --git a/lib/Support/Unix/PathV2.inc b/lib/Support/Unix/PathV2.inc index 25712a8a9f..741f44a9db 100644 --- a/lib/Support/Unix/PathV2.inc +++ b/lib/Support/Unix/PathV2.inc @@ -421,11 +421,12 @@ retry_random_path: rety_open_create: int RandomFD = ::open(RandomPath.c_str(), O_RDWR | O_CREAT | O_EXCL, mode); if (RandomFD == -1) { + int SavedErrno = errno; // If the file existed, try again, otherwise, error. - if (errno == errc::file_exists) + if (SavedErrno == errc::file_exists) goto retry_random_path; // If path prefix doesn't exist, try to create it. - if (errno == errc::no_such_file_or_directory && + if (SavedErrno == errc::no_such_file_or_directory && !exists(path::parent_path(RandomPath))) { StringRef p(RandomPath); SmallString<64> dir_to_create; @@ -440,13 +441,15 @@ rety_open_create: (*i)[1] == '/' && (*i)[2] != '/') return make_error_code(errc::no_such_file_or_directory); - if (::mkdir(dir_to_create.c_str(), 0700) == -1) + if (::mkdir(dir_to_create.c_str(), 0700) == -1 && + errno != errc::file_exists) return error_code(errno, system_category()); } } goto rety_open_create; } - return error_code(errno, system_category()); + + return error_code(SavedErrno, system_category()); } // Make the path absolute. -- cgit v1.2.3-18-g5258