diff options
author | glenda <glenda@cirno> | 2022-09-12 15:38:48 +0000 |
---|---|---|
committer | glenda <glenda@cirno> | 2022-09-12 15:38:48 +0000 |
commit | 18c383ac2da9b56a84374645eac3868de0c9331e (patch) | |
tree | 2673338b6522b1b410b6f25660b94b04a84f9814 | |
parent | 9f463939c96f8528819c66678c1be0c6333cdd11 (diff) |
Try to throw errors on C stack overflows
-rw-r--r-- | apl9.h | 8 | ||||
-rw-r--r-- | concurrency.c | 34 | ||||
-rw-r--r-- | error.c | 4 | ||||
-rw-r--r-- | functions.c | 1 |
4 files changed, 46 insertions, 1 deletions
@@ -2,6 +2,9 @@ #define MAX_LINE_LENGTH 1024 #define MAX_LINE_TOKENS 1024 +#define STACKSIZE (1024*1024) /* 1 MB */ +#define REQUIREDSTACK (16*1024) /* 16 KB */ + typedef enum { ArrayTag, @@ -53,6 +56,7 @@ typedef enum EValue = 6, EDomain = 11, ETimeout = 12, /* not in dyalog */ + EStack = 13, /* C stack overflow */ ENotImplemented = 100, /* not in dyalog */ } errorCodes; @@ -233,6 +237,7 @@ struct DfnFrame struct ThreadData { int id; + int requiredstack; DfnFrame *currentdfn; Mail *mail; Mail *lastmail; @@ -350,6 +355,9 @@ void messagesend(Array *, int); Array *messagerecv(Function, int); Array *runningtasks(void); Array *taskproperty(vlong, vlong); +int stackused(void); +int hasstack(int); +void checkstack(void); /* Monadic functions from function.c */ Array *fnNegate(Array *); diff --git a/concurrency.c b/concurrency.c index 99ca589..c01426d 100644 --- a/concurrency.c +++ b/concurrency.c @@ -2,9 +2,11 @@ #include <libc.h> #include <thread.h> #include <bio.h> + #include "apl9.h" -#define STACKSIZE (8*1024*1024) /* 8 MB */ +/* Nasty stuff to get stack size used */ +#include "/sys/src/libthread/threadimpl.h" typedef struct SpawnData SpawnData; struct SpawnData @@ -224,6 +226,7 @@ newthreaddata(Array *name) { ThreadData *td = emallocz(sizeof(ThreadData), 1); td->id = threadid(); + td->requiredstack = REQUIREDSTACK; td->currentdfn = nil; td->mail = 0; td->lastmail = 0; @@ -271,6 +274,12 @@ taskproperty(vlong t, vlong p) case 1: /* thread name */ res = fnSame(td->name); break; + case 2: /* stacksize max */ + res = mkscalarint(STACKSIZE); + break; + case 3: /* used stacksize */ + res = mkscalarint(stackused()); + break; default: unlock(&threadlock); throwerror(L"Invalid task property", EDomain); @@ -279,4 +288,27 @@ taskproperty(vlong t, vlong p) unlock(&threadlock); return res; +} + +int +stackused(void) +{ + int x; + Proc *p = _threadgetproc(); + Thread *t = p->thread; + return STACKSIZE - ((uchar*)&x - (uchar*)t->stk); +} + +int +hasstack(int n) +{ + return (n+stackused()) < STACKSIZE; +} + +void +checkstack(void) +{ + ThreadData *td = getthreaddata(); + if(!hasstack(td->requiredstack)) + throwerror(L"Not enough C stack. Stuff will go bad from now on.", EStack); }
\ No newline at end of file @@ -67,6 +67,7 @@ errorstr(int code) case EValue: err = L"VALUE ERROR"; break; case EDomain: err = L"DOMAIN ERROR"; break; case ETimeout: err = L"TIMEOUT ERROR"; break; + case EStack: err = L"STACK OVERFLOW"; break; case ENotImplemented: err = L"NOT IMPLEMENTED"; break; default: err = L""; break; } @@ -77,11 +78,14 @@ void displayerror(void) { ThreadData *td = getthreaddata(); + int tmp = td->requiredstack; + td->requiredstack = 0; Array *error = allocarray(AtypeArray, 1, 3); error->shape[0] = 3; error->arraydata[0] = mkrunearray(errorstr(td->lasterror)); error->arraydata[1] = mkrunearray(td->lasterrormsg ? td->lasterrormsg : L""); error->arraydata[2] = fnSame(td->name); rundfn(L"0::⎕RAWIO←⍵ ⋄ ('!' ⍵) ⍈ ⎕SESSION", nil, nil, nil, error); + td->requiredstack = tmp; freearray(error); }
\ No newline at end of file diff --git a/functions.c b/functions.c index 0013d8f..3559050 100644 --- a/functions.c +++ b/functions.c @@ -128,6 +128,7 @@ Array *indexOfHelper(Array *, Array *, int); Array * runfunc(Function f, Array *left, Array *right) { + checkstack(); Array *result; if(f.type == FunctypeDfn || (f.type == FunctypeOp && f.operator.type == OperatortypeDop)){ Rune *code; |