Commit 88dba610 authored by thoughtpolice's avatar thoughtpolice

Revert "Default to infinite stack size (#8189)"

This reverts commit d85044f6.
parent c798a8c6
...@@ -676,13 +676,10 @@ $ ./prog -f +RTS -H32m -S -RTS -h foo bar ...@@ -676,13 +676,10 @@ $ ./prog -f +RTS -H32m -S -RTS -h foo bar
<indexterm><primary>stack, maximum size</primary></indexterm> <indexterm><primary>stack, maximum size</primary></indexterm>
</term> </term>
<listitem> <listitem>
<para> <para>&lsqb;Default: 8M&rsqb; Set the maximum stack size for
&lsqb;Default: infinite&rsqb; Set the maximum stack an individual thread to <replaceable>size</replaceable>
size for an individual thread to bytes. If the thread attempts to exceed this limit, it will
<replaceable>size</replaceable> bytes. A setting of zero be send the <literal>StackOverflow</literal> exception.
implies no maximum stack size limit. If the thread
attempts to exceed this limit, it will be sent the
<literal>StackOverflow</literal> exception.
</para> </para>
<para> <para>
This option is there mainly to stop the program eating up This option is there mainly to stop the program eating up
......
...@@ -250,7 +250,7 @@ void getWin32ProgArgv(int *argc, wchar_t **argv[]); ...@@ -250,7 +250,7 @@ void getWin32ProgArgv(int *argc, wchar_t **argv[]);
void setWin32ProgArgv(int argc, wchar_t *argv[]); void setWin32ProgArgv(int argc, wchar_t *argv[]);
#endif #endif
void stackOverflow(StgTSO* tso); void stackOverflow(void);
void stg_exit(int n) GNU_ATTRIBUTE(__noreturn__); void stg_exit(int n) GNU_ATTRIBUTE(__noreturn__);
...@@ -268,7 +268,6 @@ int stg_sig_install (int, int, void *); ...@@ -268,7 +268,6 @@ int stg_sig_install (int, int, void *);
#define EXIT_INTERRUPTED 252 #define EXIT_INTERRUPTED 252
#define EXIT_HEAPOVERFLOW 251 #define EXIT_HEAPOVERFLOW 251
#define EXIT_KILLED 250 #define EXIT_KILLED 250
#define EXIT_STACKOVERFLOW 249
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Miscellaneous garbage Miscellaneous garbage
......
...@@ -234,7 +234,7 @@ ...@@ -234,7 +234,7 @@
* stopped for one reason or another. See typedef StgThreadReturnCode * stopped for one reason or another. See typedef StgThreadReturnCode
* in TSO.h. * in TSO.h.
*/ */
#define HeapOverflow 1 #define HeapOverflow 1 /* might also be StackOverflow */
#define StackOverflow 2 #define StackOverflow 2
#define ThreadYielding 3 #define ThreadYielding 3
#define ThreadBlocked 4 #define ThreadBlocked 4
......
...@@ -130,15 +130,9 @@ extern generation * oldest_gen; ...@@ -130,15 +130,9 @@ extern generation * oldest_gen;
StgPtr allocate(Capability *cap, W_ n) StgPtr allocate(Capability *cap, W_ n)
Allocates memory from the nursery in Allocates memory from the nursery in
the current Capability. This can be the current Capability. This can be
done without taking a global lock, done without taking a global lock,
unlike allocate(). In the event of a unlike allocate().
heap overflow the program will be
terminated.
StgPtr allocateFail(Capability *cap, W_ n)
Similar to allocate() but returns NULL
in the event of a heap overflow.
StgPtr allocatePinned(Capability *cap, W_ n) StgPtr allocatePinned(Capability *cap, W_ n)
Allocates a chunk of contiguous store Allocates a chunk of contiguous store
...@@ -160,7 +154,6 @@ extern generation * oldest_gen; ...@@ -160,7 +154,6 @@ extern generation * oldest_gen;
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
StgPtr allocate ( Capability *cap, W_ n ); StgPtr allocate ( Capability *cap, W_ n );
StgPtr allocateFail ( Capability *cap, W_ n );
StgPtr allocatePinned ( Capability *cap, W_ n ); StgPtr allocatePinned ( Capability *cap, W_ n );
/* memory allocator for executable memory */ /* memory allocator for executable memory */
......
...@@ -94,7 +94,7 @@ void initRtsFlagsDefaults(void) ...@@ -94,7 +94,7 @@ void initRtsFlagsDefaults(void)
RtsFlags.GcFlags.statsFile = NULL; RtsFlags.GcFlags.statsFile = NULL;
RtsFlags.GcFlags.giveStats = NO_GC_STATS; RtsFlags.GcFlags.giveStats = NO_GC_STATS;
RtsFlags.GcFlags.maxStkSize = 0; /* off by default */ RtsFlags.GcFlags.maxStkSize = (8 * 1024 * 1024) / sizeof(W_);
RtsFlags.GcFlags.initialStkSize = 1024 / sizeof(W_); RtsFlags.GcFlags.initialStkSize = 1024 / sizeof(W_);
RtsFlags.GcFlags.stkChunkSize = (32 * 1024) / sizeof(W_); RtsFlags.GcFlags.stkChunkSize = (32 * 1024) / sizeof(W_);
RtsFlags.GcFlags.stkChunkBufferSize = (1 * 1024) / sizeof(W_); RtsFlags.GcFlags.stkChunkBufferSize = (1 * 1024) / sizeof(W_);
...@@ -233,7 +233,7 @@ usage_text[] = { ...@@ -233,7 +233,7 @@ usage_text[] = {
" -? Prints this message and exits; the program is not executed", " -? Prints this message and exits; the program is not executed",
" --info Print information about the RTS used by this program", " --info Print information about the RTS used by this program",
"", "",
" -K<size> Sets the maximum stack size (defaults to infinite) Egs: -K32k -K512k", " -K<size> Sets the maximum stack size (default 8M) Egs: -K32k -K512k",
" -ki<size> Sets the initial thread stack size (default 1k) Egs: -ki4k -ki2m", " -ki<size> Sets the initial thread stack size (default 1k) Egs: -ki4k -ki2m",
" -kc<size> Sets the stack chunk size (default 32k)", " -kc<size> Sets the stack chunk size (default 32k)",
" -kb<size> Sets the stack chunk buffer size (default 1k)", " -kb<size> Sets the stack chunk buffer size (default 1k)",
......
...@@ -114,12 +114,12 @@ stgFree(void* p) ...@@ -114,12 +114,12 @@ stgFree(void* p)
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
void void
stackOverflow(StgTSO* tso) stackOverflow(void)
{ {
StackOverflowHook(tso->tot_stack_size * sizeof(W_)); StackOverflowHook(RtsFlags.GcFlags.maxStkSize * sizeof(W_));
#if defined(TICKY_TICKY) #if defined(TICKY_TICKY)
if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo(); if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
#endif #endif
} }
......
...@@ -393,7 +393,7 @@ schedule (Capability *initialCapability, Task *task) ...@@ -393,7 +393,7 @@ schedule (Capability *initialCapability, Task *task)
run_thread: run_thread:
// CurrentTSO is the thread to run. It might be different if we // CurrentTSO is the thread to run. t might be different if we
// loop back to run_thread, so make sure to set CurrentTSO after // loop back to run_thread, so make sure to set CurrentTSO after
// that. // that.
cap->r.rCurrentTSO = t; cap->r.rCurrentTSO = t;
......
...@@ -499,8 +499,7 @@ threadStackOverflow (Capability *cap, StgTSO *tso) ...@@ -499,8 +499,7 @@ threadStackOverflow (Capability *cap, StgTSO *tso)
IF_DEBUG(sanity,checkTSO(tso)); IF_DEBUG(sanity,checkTSO(tso));
if ( (RtsFlags.GcFlags.maxStkSize > 0) // don't throw if we have infinite stack if (tso->tot_stack_size >= RtsFlags.GcFlags.maxStkSize
&& (tso->tot_stack_size >= RtsFlags.GcFlags.maxStkSize)
&& !(tso->flags & TSO_BLOCKEX)) { && !(tso->flags & TSO_BLOCKEX)) {
// NB. never raise a StackOverflow exception if the thread is // NB. never raise a StackOverflow exception if the thread is
// inside Control.Exceptino.block. It is impractical to protect // inside Control.Exceptino.block. It is impractical to protect
...@@ -576,12 +575,7 @@ threadStackOverflow (Capability *cap, StgTSO *tso) ...@@ -576,12 +575,7 @@ threadStackOverflow (Capability *cap, StgTSO *tso)
"allocating new stack chunk of size %d bytes", "allocating new stack chunk of size %d bytes",
chunk_size * sizeof(W_)); chunk_size * sizeof(W_));
new_stack = (StgStack*) allocateFail(cap, chunk_size); new_stack = (StgStack*) allocate(cap, chunk_size);
if (new_stack == NULL) {
// We've really run out of memory in the heap, so die.
stackOverflow(tso);
stg_exit(EXIT_STACKOVERFLOW);
}
SET_HDR(new_stack, &stg_STACK_info, old_stack->header.prof.ccs); SET_HDR(new_stack, &stg_STACK_info, old_stack->header.prof.ccs);
TICK_ALLOC_STACK(chunk_size); TICK_ALLOC_STACK(chunk_size);
......
...@@ -624,27 +624,27 @@ move_STACK (StgStack *src, StgStack *dest) ...@@ -624,27 +624,27 @@ move_STACK (StgStack *src, StgStack *dest)
} }
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
allocateFail() allocate()
This allocates memory in the current thread - it is intended for This allocates memory in the current thread - it is intended for
use primarily from STG-land where we have a Capability. use primarily from STG-land where we have a Capability. It is
better than allocate() because it doesn't require taking the
sm_mutex lock in the common case.
Memory is allocated directly from the nursery if possible (but not Memory is allocated directly from the nursery if possible (but not
from the current nursery block, so as not to interfere with from the current nursery block, so as not to interfere with
Hp/HpLim). Hp/HpLim).
We return NULL in the event of a heap overflow.
-------------------------------------------------------------------------- */ -------------------------------------------------------------------------- */
StgPtr StgPtr
allocateFail (Capability *cap, W_ n) allocate (Capability *cap, W_ n)
{ {
bdescr *bd; bdescr *bd;
StgPtr p; StgPtr p;
TICK_ALLOC_HEAP_NOCTR(WDS(n)); TICK_ALLOC_HEAP_NOCTR(WDS(n));
CCS_ALLOC(cap->r.rCCCS,n); CCS_ALLOC(cap->r.rCCCS,n);
if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) { if (n >= LARGE_OBJECT_THRESHOLD/sizeof(W_)) {
W_ req_blocks = (W_)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE; W_ req_blocks = (W_)BLOCK_ROUND_UP(n*sizeof(W_)) / BLOCK_SIZE;
...@@ -655,7 +655,14 @@ allocateFail (Capability *cap, W_ n) ...@@ -655,7 +655,14 @@ allocateFail (Capability *cap, W_ n)
req_blocks >= HS_INT32_MAX) // avoid overflow when req_blocks >= HS_INT32_MAX) // avoid overflow when
// calling allocGroup() below // calling allocGroup() below
{ {
return NULL; // heap overflow heapOverflow();
// heapOverflow() doesn't exit (see #2592), but we aren't
// in a position to do a clean shutdown here: we
// either have to allocate the memory or exit now.
// Allocating the memory would be bad, because the user
// has requested that we not exceed maxHeapSize, so we
// just exit.
stg_exit(EXIT_HEAPOVERFLOW);
} }
ACQUIRE_SM_LOCK ACQUIRE_SM_LOCK
...@@ -675,12 +682,12 @@ allocateFail (Capability *cap, W_ n) ...@@ -675,12 +682,12 @@ allocateFail (Capability *cap, W_ n)
bd = cap->r.rCurrentAlloc; bd = cap->r.rCurrentAlloc;
if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) { if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
// The CurrentAlloc block is full, we need to find another // The CurrentAlloc block is full, we need to find another
// one. First, we try taking the next block from the // one. First, we try taking the next block from the
// nursery: // nursery:
bd = cap->r.rCurrentNursery->link; bd = cap->r.rCurrentNursery->link;
if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) { if (bd == NULL || bd->free + n > bd->start + BLOCK_SIZE_W) {
// The nursery is empty, or the next block is already // The nursery is empty, or the next block is already
// full: allocate a fresh block (we can't fail here). // full: allocate a fresh block (we can't fail here).
...@@ -713,36 +720,6 @@ allocateFail (Capability *cap, W_ n) ...@@ -713,36 +720,6 @@ allocateFail (Capability *cap, W_ n)
return p; return p;
} }
/* -----------------------------------------------------------------------------
allocate()
This allocates memory in the current thread - it is intended for
use primarily from STG-land where we have a Capability.
Memory is allocated directly from the nursery if possible (but not
from the current nursery block, so as not to interfere with
Hp/HpLim).
We crash with a HeapOverflow when the allocation fails.
-------------------------------------------------------------------------- */
StgPtr
allocate (Capability *cap, W_ n)
{
StgPtr p = allocateFail(cap, n);
if (p == NULL) {
heapOverflow();
// heapOverflow() doesn't exit (see #2592), but we aren't
// in a position to do a clean shutdown here: we
// either have to allocate the memory or exit now.
// Allocating the memory would be bad, because the user
// has requested that we not exceed maxHeapSize, so we
// just exit.
stg_exit(EXIT_HEAPOVERFLOW);
}
return p;
}
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
Allocate a fixed/pinned object. Allocate a fixed/pinned object.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment