Comments on: Evaluation quotas (limits)
We've discussed this for many years... and now, in A75, you can set secure to limit interpreter evaluation. This feature allows you to restrict server scripts (such as CGI) to a specific evaluation length to prevent runaway programs.
This example sets the limit to 50000 cycles, after which the program will immediately quit (the default behavior):
>> secure [eval 50000]
>> loop 100000 [next "test"]
Also, for debugging you can use the more detailed form of secure:
>> secure [eval [throw 50000]]
>> loop 100000 [next "test"]
** Access error: security violation: eval
** Where: loop
** Near: loop 100000 [next "test"]
You can continue your debugging at the console, but secure will trap again on the next evaluation sample. To disable that behavior:
>> secure [eval allow]
When tuning your program, to determine how many cycles your code needs, you can use:
However, add to that number a good margin of error for special conditions within your code. In many cases you will want to make it ten or twenty times larger, just to be sure.
A few notes:
- The maximum evaluation limit is 2 ** 63(9e18).
- The evaluation limit can be set only once and cannot be reset. However, for debugging after an eval THROW exception, you can use secure to disable the trap (use: [eval allow]).
- The limit is approximate. It is sampled at regular intervals (to avoid slowing down evaluation.) The sampling period is 10000 cycles, so that is the resolution of the limit. For example, if you set the limit to 1, it won't trap an error until 10000.
- If the program quits, the exit code is set to 101, the same as any security termination; however, we may want to use special codes to indicate the reason for the quit.
- Some types of loops are not yet checked, but we will add them. For example, PARSE cycles are not yet counted.
- Time limits are not yet supported, but may be added in the future. However, the cycle limit is better for most cases, because it is CPU speed independent.
Uh, call me dumb, but what measure is it actually to use "cycles"? I have seen nothing like that with other langs. Well, OTOH I did not checked properly. But what I would expect is two arguments:
- memory used
Those above two will be imo understood by most user more easily. Could those be added next to "cycles"? It is imo MUCH easer to guess for how long my script will run at max, and how many RAM it should consume at max, than uh, counting cycles? Sounds too abstract for me.
And also - what if my script hangs in some section, waiting for something? Are cycles counted in such case? Because then time limit would apply nicely. The RAM consume limit will be really needed though, for CGI like server purposes ...
Cycles are a relative measurement of evaluation. Think of them like instructions on a CPU. The number of instruction cycles is a better measurement than time, because time depends on CPU speed. If you test your code on a 500MHz Linux box at home, then upload it to a 3GHz server, the time it takes to execute is much different, but the cycle count will be identical. It is a much more consistent and fair method.
With regard to memory, languages like REBOL use garbage collection, so memory consumption isn't a good indicator. Many of my server scripts run for years on 8 MB of memory. In addition, memory consumption often fluctuates in an unpredictable manner due to memory segmenting and caching.
So, with that being said, it's certainly possible to add both time and memory limits to the system. However, for right now, I wanted what was the most powerful for advanced programmers. In addition, both time and memory limits can be controlled at the process level on any good operating system (independent of REBOL.)
Understood. I just once read some article, how ISP refused some CGI tool, because they could not control it by setting how long the process runs, and how much RAM at max it consumes. They were probably afraid of some memory leaks, and to be fair, we had some leaks in REBOL in the past, so that process consumed all memory. At least memory parameter is imo more important than time parameter.
btw - will it be possible to set such eval limitations from command-line somehow? Simply to allow external script control?
However, for right now, I wanted what was the most powerful for advanced programmers.
As I generally understand it, ISPs use time and memory restrictions for silly programmers, not those who know what they are doing. :-)
What about using the memory restriction feature to simulate an embedded environment?
Even as a start, this is *great*. Of course, time and memory options would be fantastic. Even with fluctuations, you should be able to set a limit of 500MB or 1GB to catch truly catastrophic situations, where you know your app should never use more than ~25MB.
As you say, assuming the app gets to execute user code, we can handle time and memory limits ourselves (and it would make a good example). For something like a runaway parse rule, this could be great.
Seeing as CGI is mentioned here, I was wondering is there a good reason why CGI with R3 seems only to work on Linux, and not on Windows?
I've tried all recent builds including r3-a75.exe but I always get "Internal Server Error" when doing a hello world script that is fine with R2. (tried apache).
here's a blog, which discusses how to run CGI under R3. Dunno if it will work under Windows, but it could:
So, is the conclusion, that if not 'time, then 'memory limitation is an absolute must? I do remember View script memory leak, eating memory. As Henrik mentions, it is probably also good for simulation of constrained environments (embedded).
The only problem I can see with 'memory parameter is, that when REBOL would reach such a limit, it would quit, whereas in embedded environment, the system can start eventually swapping, depending upon underlying OS. But anyway - I hope that 'memory limitation will be added later ...
I tried running the script from http://www.rebol.net/r3blogs/0182.html but it has the same problems on windows.
When I can get cgi I can start to port legacy apps.
IMHO the limit counter has to be resettable within the app... applications are meant to be run perpetually or for an extended period of time... not being able to reset the limit makes it useless in that situation... I might want to ensure that only a specific set of funcs don't overun the limits...|
Post a Comment:
You can post a comment here. Keep it on-topic.