# HG changeset patch # User Francisco J Ballesteros # Date 1317743460 0 # Node ID afb3b2c5d05deb7bb36e85d38be9b213ed9e3d3d # Parent d4d0416eb4ec70b89c2dac6f0233516973bfd715 oom: out of memory error handling revisited. liberror is gone. outofmemoryexits(2) may change the default behaviour of routines in malloc(2) so that they call sysfatal instead of returning 0. i.e., no new functions emalloc, estrdup, ... are needed at all. R=nix-dev, quanstro, nemo, rminnich CC=nix-dev http://codereview.appspot.com/5181041 diff -r d4d0416eb4ec -r afb3b2c5d05d sys/include/error.h --- a/sys/include/error.h Mon Oct 03 16:40:05 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -#pragma lib "liberror.a" -#pragma src "/sys/src/liberror" - -typedef struct Channel Channel; - -#pragma incomplete Channel; - -#pragma varargck argpos esmprint 1 - -char* estrdup(char*); -void* emalloc(int); -void* emallocz(int, int); -void* erealloc(void*,int); -char* esmprint(char *fmt, ...); -Channel*echancreate(int, int); diff -r d4d0416eb4ec -r afb3b2c5d05d sys/include/libc.h --- a/sys/include/libc.h Mon Oct 03 16:40:05 2011 +0200 +++ b/sys/include/libc.h Tue Oct 04 15:51:00 2011 +0000 @@ -100,6 +100,7 @@ extern ulong getmalloctag(void*); extern ulong getrealloctag(void*); extern void* malloctopoolblock(void*); +extern void outofmemoryexits(int); /* * print routines diff -r d4d0416eb4ec -r afb3b2c5d05d sys/man/2/error --- a/sys/man/2/error Mon Oct 03 16:40:05 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -.TH ERROR 2 -.SH NAME -estrdup, emalloc, emallocz, erealloc, esmprint, echancreate \- error handling utilities -.SH SYNOPSIS -.B #include -.br -.B #include -.br -.B #include -.PP -.B -char* estrdup(char*) -.br -.B -void* emalloc(int); -.br -.B -void* emallocz(int, int); -.br -.B -void* erealloc(void*,int) -.br -.B -void* esmprint(char *fmt, ...) -.br -.B -Channel* echancreate(int, int) -.br -.SH DESCRIPTION -These routiles are tools for error handling verions of memory allocation -functions found elsewhere. -.PP -Their are named like standard functions with the letter -.B e -prepended, and behave as expected for the -standard function in each case. However, they check that the standard routine did its -work and call -.IR sysfatal (2) -otherwise. -All of them set the caller PC as the tag, using -.IR setmalloctag (2). -.PP -.I Echancreate -requires including the header for -.I thread (2). -Other ones do not. -.SH SOURCE -.B /sys/src/liberror diff -r d4d0416eb4ec -r afb3b2c5d05d sys/man/2/malloc --- a/sys/man/2/malloc Mon Oct 03 16:40:05 2011 +0200 +++ b/sys/man/2/malloc Tue Oct 04 15:51:00 2011 +0000 @@ -43,6 +43,9 @@ .B void* malloctopoolblock(void*) .PP +.B +void outofmemoryexits(int) +.PP .SH DESCRIPTION .I Malloc and @@ -214,6 +217,14 @@ .I acid can be used to obtain traces of malloc execution; see .IR acid (1). +.PP +If +.I outofmemoryexits +is called with a non-zero argument, any memory allocation +failed due to out of memory conditions is handled by calling +.IR sysfatal (2) +instead of returning an error indication to the user. Calling +it with zero restores normal behavior. .SH BUGS The different specification of .I calloc diff -r d4d0416eb4ec -r afb3b2c5d05d sys/src/libc/port/malloc.c --- a/sys/src/libc/port/malloc.c Mon Oct 03 16:40:05 2011 +0200 +++ b/sys/src/libc/port/malloc.c Tue Oct 04 15:51:00 2011 +0000 @@ -34,9 +34,18 @@ .panic= ppanic, .private= &sbrkmempriv, }; + +static int oomexits; + Pool *mainmem = &sbrkmem; Pool *imagmem = &sbrkmem; +void +outofmemoryexits(int yn) +{ + oomexits = yn; +} + /* * we do minimal bookkeeping so we can tell pool * whether two blocks are adjacent and thus mergeable. @@ -205,6 +214,8 @@ void *v; v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); + if(oomexits && v == nil) + sysfatal("out of memory"); if(Npadlong && v != nil) { v = (ulong*)v+Npadlong; setmalloctag(v, getcallerpc(&size)); @@ -219,6 +230,8 @@ void *v; v = poolalloc(mainmem, size+Npadlong*sizeof(ulong)); + if(oomexits && v == nil) + sysfatal("out of memory"); if(Npadlong && v != nil){ v = (ulong*)v+Npadlong; setmalloctag(v, getcallerpc(&size)); @@ -235,6 +248,8 @@ void *v; v = poolallocalign(mainmem, size+Npadlong*sizeof(ulong), align, offset-Npadlong*sizeof(ulong), span); + if(oomexits && v == nil) + sysfatal("out of memory"); if(Npadlong && v != nil){ v = (ulong*)v+Npadlong; setmalloctag(v, getcallerpc(&size)); @@ -270,6 +285,8 @@ if(v == nil) setmalloctag(nv, getcallerpc(&v)); } + if(oomexits && nv == nil) + sysfatal("out of memory"); return nv; } diff -r d4d0416eb4ec -r afb3b2c5d05d sys/src/liberror/echancreate.c --- a/sys/src/liberror/echancreate.c Mon Oct 03 16:40:05 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -#include -#include -#include -#include - -Channel* -echancreate(int sz, int n) -{ - Channel *c; - - c = chancreate(sz, n); - if(c == nil) - sysfatal("chancreate: %r"); - return c; -} diff -r d4d0416eb4ec -r afb3b2c5d05d sys/src/liberror/emalloc.c --- a/sys/src/liberror/emalloc.c Mon Oct 03 16:40:05 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -#include -#include -#include - -char* -estrdup(char* s) -{ - s = strdup(s); - if(s == nil) - sysfatal("estrdup: not enough memory"); - setmalloctag(s, getcallerpc(&s)); - return s; -} - -void* -emalloc(int sz) -{ - void* s; - - s = mallocz(sz, 1); - if(s == nil) - sysfatal("emalloc: not enough memory"); - setmalloctag(s, getcallerpc(&sz)); - return s; -} - -void* -emallocz(int sz, int zero) -{ - void* s; - - s = mallocz(sz, zero); - if(s == nil) - sysfatal("emalloc: not enough memory"); - setmalloctag(s, getcallerpc(&sz)); - return s; -} - -void* -erealloc(void* p, int sz) -{ - - p = realloc(p, sz); - if(p == nil) - sysfatal("erealloc: not enough memory"); - setmalloctag(p, getcallerpc(&p)); - return p; -} - -char* -esmprint(char *fmt, ...) -{ - va_list arg; - char *m; - - va_start(arg, fmt); - m = vsmprint(fmt, arg); - va_end(arg); - if(m == nil) - sysfatal("smprint: %r"); - setmalloctag(m, getcallerpc(&fmt)); - return m; -} diff -r d4d0416eb4ec -r afb3b2c5d05d sys/src/liberror/mkfile --- a/sys/src/liberror/mkfile Mon Oct 03 16:40:05 2011 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -