Skip to content

Commit 194b6a3

Browse files
committed
If possible, set the stack rlimit to at least 8MiB on cc1 startup, and work
around a Linux kernel bug where the actual amount of available stack may be a *lot* lower than the rlimit. GCC also sets a higher stack rlimit on startup, but it goes all the way to 64MiB. We can increase this limit if it proves necessary. The kernel bug is as follows: Linux kernels prior to version 4.1 may choose to map the process's heap as little as 128MiB before the process's stack for a PIE binary, even in a 64-bit virtual address space. This means that allocating more than 128MiB before you reach the process's stack high water mark can lead to crashes, even if you don't recurse particularly deeply. We work around the kernel bug by touching a page deep within the stack (after ensuring that we know how big it is), to preallocate virtual address space for the stack so that the kernel doesn't allow the brk() area to wander into it, when building clang as a Linux PIE binary. llvm-svn: 278882
1 parent 6331dc1 commit 194b6a3

File tree

1 file changed

+65
-0
lines changed

1 file changed

+65
-0
lines changed

clang/tools/driver/cc1_main.cpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,21 @@
2525
#include "clang/Frontend/Utils.h"
2626
#include "clang/FrontendTool/Utils.h"
2727
#include "llvm/ADT/Statistic.h"
28+
#include "llvm/Config/config.h"
2829
#include "llvm/LinkAllPasses.h"
2930
#include "llvm/Option/ArgList.h"
3031
#include "llvm/Option/OptTable.h"
32+
#include "llvm/Support/Compiler.h"
3133
#include "llvm/Support/ErrorHandling.h"
3234
#include "llvm/Support/ManagedStatic.h"
3335
#include "llvm/Support/Signals.h"
3436
#include "llvm/Support/TargetSelect.h"
3537
#include "llvm/Support/Timer.h"
3638
#include "llvm/Support/raw_ostream.h"
3739
#include <cstdio>
40+
#if HAVE_SYS_RESOURCE_H
41+
#include <sys/resource.h>
42+
#endif
3843
using namespace clang;
3944
using namespace llvm::opt;
4045

@@ -64,7 +69,67 @@ void initializePollyPasses(llvm::PassRegistry &Registry);
6469
}
6570
#endif
6671

72+
#if HAVE_SYS_RESOURCE_H && HAVE_GETRLIMIT && HAVE_SETRLIMIT
73+
// The amount of stack we think is "sufficient". If less than this much is
74+
// available, we may be unable to reach our template instantiation depth
75+
// limit and other similar limits.
76+
// FIXME: Unify this with the stack we request when spawning a thread to build
77+
// a module.
78+
static const int kSufficientStack = 8 << 20;
79+
80+
#if defined(__linux__) && defined(__PIE__)
81+
LLVM_ATTRIBUTE_NOINLINE
82+
static void ensureStackAddressSpace() {
83+
// Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
84+
// relatively close to the stack (they are only guaranteed to be 128MiB
85+
// apart). This results in crashes if we happen to heap-allocate more than
86+
// 128MiB before we reach our stack high-water mark.
87+
//
88+
// To avoid these crashes, ensure that we have sufficient virtual memory
89+
// pages allocated before we start running by touching an early page. (We
90+
// allow 512KiB for kernel/libc-provided data such as command-line arguments
91+
// and environment variables, and for main and cc1_main)
92+
volatile char ReservedStack[kSufficientStack - 512 * 1024];
93+
volatile int N = 0;
94+
(void)+ReservedStack[N];
95+
}
96+
#else
97+
static void ensureStackAddressSpace() {}
98+
#endif
99+
100+
/// Attempt to ensure that we have at least 8MiB of usable stack space.
101+
static void ensureSufficientStack() {
102+
struct rlimit rlim;
103+
if (getrlimit(RLIMIT_STACK, &rlim) != 0)
104+
return;
105+
106+
// Increase the soft stack limit to our desired level, if necessary and
107+
// possible.
108+
if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < kSufficientStack) {
109+
// Try to allocate sufficient stack.
110+
if (rlim.rlim_max == RLIM_INFINITY || rlim.rlim_max >= kSufficientStack)
111+
rlim.rlim_cur = kSufficientStack;
112+
else if (rlim.rlim_cur == rlim.rlim_max)
113+
return;
114+
else
115+
rlim.rlim_cur = rlim.rlim_max;
116+
117+
if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||
118+
rlim.rlim_cur != kSufficientStack)
119+
return;
120+
}
121+
122+
// We should now have a stack of size at least kSufficientStack. Ensure
123+
// that we can actually use that much, if necessary.
124+
ensureStackAddressSpace();
125+
}
126+
#else
127+
static void ensureSufficientStack() {
128+
#endif
129+
67130
int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) {
131+
ensureSufficientStack();
132+
68133
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
69134
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
70135

0 commit comments

Comments
 (0)