LinuxQuestions.org
Visit Jeremy's Blog.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 08-12-2003, 04:02 AM   #1
hfawzy
Member
 
Registered: Aug 2002
Location: Egypt
Distribution: Debian Sarge, Slackware 10.0
Posts: 163

Rep: Reputation: 30
setrlimit


Hi there,
I'm trying to restrict the data and stack segments used by a program.
I tried to use setrlimit, but it doesn't seem to have any effect on the program. Isn't it supposed to kill the program as soon as the data or stack segment size exceeds a certain value (that I set using setrlimit)?
Here's the C code I used:

Code:
int data_limit = 1024 * 1024 * 4;
int stack_limit = 1024 * 1024 * 2;

struct rlimit myrlimit;

rl.rlim_cur = data_limit;
rl.rlim_max = data_limit;
setrlimit(RLIMIT_DATA, &myrlimit);

rl.rlim_cur = stack_limit;
rl.rlim_max = stack_limit;
setrlimit(RLIMIT_STACK, &myrlimit);
Thanks in advance!
 
Old 08-12-2003, 12:28 PM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Personally I've never used setrlimit(), but from the man page I understand that setrlimit(RLIMIT_DATA, ...) does not send a signal when the process reaches its data-limit. Only RLIMIT_STACK should cause termination of your program with a segfault when it exceeds the stack limit.

If you tried to exceed the stacksize, and your program does not get terminated, maybe the call setrlimit(RLIMIT_STACK, ... ) didn't succeed for some reason. Try checking the return-value of setrlimit() to find out if the call really succeeds.

Note that if the process does not run as root, could be a reason for setrlimit() to fail.
 
Old 08-14-2003, 02:27 AM   #3
hfawzy
Member
 
Registered: Aug 2002
Location: Egypt
Distribution: Debian Sarge, Slackware 10.0
Posts: 163

Original Poster
Rep: Reputation: 30
Thanks for your reply..
But now how could I know if the process used more data than I allowed (using setrlimit) , so I can then kill it?

Also, I wanted to be sure about the RLIMIT_DATA thing..

If for example I define:

char ch[10000000];

This array of characters uses 10000000 / 1024 / 1024 = 9.53 MB of data, right? And RLIMIT_DATA limits this value (9.53MB), right?

Regards,
Hfawzy.
 
Old 08-14-2003, 06:13 AM   #4
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
When you declare char ch[10000] locally (function parameter, or non-static local variable declared inside a function), the space for this (10000 bytes) is allocated on the stack. So mem space for local var's can exceed the stack limit, but not the data limit. Exceeding stack limit will terminate the process automatically with a SIGXFSZ signal.

The data limit limits memory dynamically allocated on the heap. In this case malloc() will fail if it exceeds the data limit and return a NULL pointer. Checking for this condition is always a good idea (as you already know I suppose). E.g.:
Code:
char *str;
str = (char *) malloc(1000);
if (str == NULL) {
    fputs("Memory limit exceeded", stderr);
    abort();
}
This leaves the cases of declaring a global or static variable. I'm not sure about this. I don't know where exactly these var's are stored (heap? or even code space?).

A wild guess about this is that memory for these kind of var's get allocated when the process first starts, so before a limit is set.... But, as I said this is a wild guess, and I have yet to try these things to find out.

If you do find out, I would appreciate it if you could post it here.
 
Old 08-14-2003, 02:15 PM   #5
hfawzy
Member
 
Registered: Aug 2002
Location: Egypt
Distribution: Debian Sarge, Slackware 10.0
Posts: 163

Original Poster
Rep: Reputation: 30
Thanks for your reply! I really appreciate your help..
Now, when I try this code I expected to get a message "aborted", but it isn't the case.. It doesn't work..

Code:
int main() {

	struct rlimit myrlimit;
	
	myrlimit.rlim_cur = 0;
	myrlimit.rlim_max = 0;
	
	setrlimit(RLIMIT_DATA, &myrlimit);

	char *str;
	str = (char *) malloc(10000000);
	
	if (str == NULL) {
		printf("aborted\n");
		abort();
	}
	
	return 0;

}
Regards,
Hfawzy

Last edited by hfawzy; 08-14-2003 at 02:48 PM.
 
Old 08-14-2003, 02:42 PM   #6
kev82
Senior Member
 
Registered: Apr 2003
Location: Lancaster, England
Distribution: Debian Etch, OS X 10.4
Posts: 1,263

Rep: Reputation: 51
perhaps you should check if the call to setrlimit is failing?
 
Old 08-14-2003, 02:47 PM   #7
hfawzy
Member
 
Registered: Aug 2002
Location: Egypt
Distribution: Debian Sarge, Slackware 10.0
Posts: 163

Original Poster
Rep: Reputation: 30
In fact I checked the return value of setrlimit, and I got 0 (it succeeded)..

Thanks..
Hfawzy..
 
Old 08-18-2003, 11:16 AM   #8
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
I've found out that RLIMIT_DATA only effect sbrk() and brk() calls, and that malloc() of recent versions of glibc (or is it the kernel?) don't call brk() anymore to do the allocation.... That explains why it doesn't work.

A solution could be to RLIMIT_AS instead of RLIMIT_DATA.
You may have overseen this RLIMIT_AS (as I first did), because, on my system (debian sarge) it is not mentioned in the man-page, but it is in de info-doc's of glibc.

RLIMIT_AS limit all memory, including globals, statics, malloc's, and I think even code and environment memory (but probably not local var's as thay are on the stack). So there may be some calculation needed to determine what the actual limit value should be.

As far as I understand the mechanics behind all this, it does work a little awkward. E.g. when malloc-ing 1 byte it aborts with a limit of 1212415, but it succeeds with a limit of 1212416 (on my system). And when I set the limit to 10000000 (ten million), I can malloc 8000000 bytes (eight million) succesfully, but it aborts on 9000000 (nine million).

You may want to play with the numbers to find out how it works. If you find something interesting, please post it here. TIA.

Example:
Code:
#include <stdlib.h>
#include <stdio.h>
#include <sys/resource.h>
#include <unistd.h>

int main()
{
     char *str;
     struct rlimit myrlimit;
	
     getrlimit(RLIMIT_DATA, &myrlimit);
     myrlimit.rlim_cur = 10000000;
     setrlimit(RLIMIT_AS, &myrlimit);

     str = (char *) malloc(8000000);    /* 9000000 fails on my system */
     if (str == NULL) {
	  abort();     /* abort() prints "Aborted" to stderr itself. */
     }
     return 0;
}
 
Old 08-18-2003, 04:03 PM   #9
hfawzy
Member
 
Registered: Aug 2002
Location: Egypt
Distribution: Debian Sarge, Slackware 10.0
Posts: 163

Original Poster
Rep: Reputation: 30
Thanks,
I'll try that and will get back to you as soon as possible
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:07 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration