lkml.org 
[lkml]   [2000]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
Date
From
SubjectRe: Overcomittable memory
James Sutherland wrote:
> On 28 Mar 2000 00:26:37 GMT, you wrote:
> >On 21 Mar 2000 23:36:59 +0100, Marco Colombo <marco@esi.it> wrote:

> >reserving some memory only for kernel and/or root, etc, but it will just
> >lower the chances for OOM, not eliminate it.
> >
> >OOM will still happen, and we need some handling when it hits us. killing
> >random process is at least guaranteed to be fair as far as it goes, but
> >fairness is not necessarily the most sane thing to do in all cases...
>
> Not necessarily "killing" - just "signalling". Properly written, a
> program should be able to handle the signal and exit gracefully. If it
> doesn't handle a "something's wrong" signal, can we expect it to check
> every malloc() call for an equivalent return value?

Have you tried implementing a program that handles SIGBUS? It's a bloody
nightmare that will drive you insane (especially if you plan on using
threads).

I think I have previously sent an example pseudo-program demonstrating
this. But for other viewers in linux-kernel who may have missed it:

(I've modified this to say mmap instead of malloc to satisy some pedants
out there...)

---

Example program where mmap returns ENOMEM deterministically at point of
allocation:

main()
{
syscall_just_this_process_overcommit(0);

char *p = (char *) mmap(NULL, 1048576, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(!p) {
printf("Hey we ran out of memory!\n");
return ENOMEM;
}
// this memory is guaranteed safe to acces
for(int i=0; i<1048576; i++) *p++ = i;
// some other stuff...
free(p);
return 0;
}

---

Example program where mmap returns memory regardless of ability to page.
SIGBUS returned non-deterministically and asynschronously:

void *bailout_addr = NULL;
void mysig() {
if(bailout_addr)
set_interrupted_address_somehow(bailout_addr);
}

main()
{
char *p = (char *) mmap(NULL, 1048576, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if(!p) goto bailout;

bailout_addr = bailout;
signal(SIGBUS, mysig);
for(int i=0; i<1048576; i++) *p++ = i;
// etc...
free(p);
return 0;
bailout:
printf("Hey we ran out of memory!\n");
return ENOMEM;
}

Yes, the second example lacks sigstack etc, but you can assign fixed
stacks etc. In reality it's very hard to actually overrun your stack if
you write code knowing it's limited. Other problems include executable
pages being paged out and then faulted (==SIGBUS with handler on disk
not in memory). You can mlock() to get around that, but then you need to
be root, and mlock()'ing of executable pages from devices is broken
anyway.

---

Now, which of these two examples do you suppose is easier to write and
maintain? At any rate, a program which doesn't check the return value of
malloc/mmap etc is either a quick hack or it's plain BROKEN.

Nobody writes a SIGBUS handler because it's just not practical. If, on
the other hand, somebody can demonstrate a nice way of doing so, I would
be happy to use it :)

--
John Ripley, empeg Ltd.
http://www.empeg.com

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:57    [W:0.040 / U:0.648 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site