File descriptor limits and default stack sizes

Where I work, we create and distribute a library and a couple of complex programs built on this library. All code is written in C and is available on most "standard" systems, such as Windows, Linux, Aix, Solaris, Darwin.

I started working in the QA department and during the execution of tests I have been reminded several times lately that I need to remember to set file descriptor limits and default stack sizes higher or something bad. This is especially true for Solaris and now Darwin.

Now this is very strange for me, because I believe that in a zero environment work is required to make the product work. Therefore, I wonder if there are times when such a requirement is a necessary evil, or if we are doing something wrong.

Edit:

Great comments that describe the problem and a bit of background. However, I do not believe that I correctly formulated this question. We currently require customers, and therefore testers, to set these limits before running our code. We do not do this programmatically. And this is not the situation when they CAN WIN, under normal load, our programs will end and disappear. Therefore, when rewriting the question, is it required that the client change these ulimit values ​​in order to run our software, which is expected on some platforms, that is, Solaris, Aix, or we, as a company, making it difficult for these users to migrate?

Bounty: I added generosity to hope to get a little more information about what other companies are doing to manage these restrictions. Can you install them pragmatically? Should we? Should our programs even fall within these limits, or could this be a sign that things might be a little dirty under the covers? This is really what I want to know, because the perfectionist, apparently the dirty program really bothers me.

+4
source share
7 answers

If you need to change these values ​​to run QA tests, this is not a big deal. However, requiring the client to do this in order for the program to start, it should be avoided (IMHO). If nothing else, create a script wrapper that sets these values ​​and launches the application so that users still have the application launch with one click. However, their use within the program will be preferable. At the very least, ask the program to check the limits at its launch and the (clean) error earlier if the limits are too low.

If a software developer told me that I had to tinker with my limitations on the stack and descriptor to run their program, this will change my perception of the software. This would make me wonder: “Why should they exceed system limits, which seem to be acceptable for any other software that I have?” This may or may not be a real problem, but asking to do something that (for many) may seem hacker does not have the same professional advantage as the program that you just start and leave.

This problem seems even worse when you say: "This is not a situation where they MAY BE run out, under normal load, our programs will end and an error will occur." A program that exceeds these limits is one thing, but a program that does not gracefully handle error conditions that result from exceeding these limits is completely different. If you click on the file descriptor restriction and try to open the file, you should receive an error message indicating that you have too many files. This should not cause the program to crash in a well-designed program. It may be harder to spot problems using the stack, but executing file descriptors should never fail.

You do not give details about what type of program it is, but I would say that it is not safe to assume that users of your program will necessarily have the appropriate permissions to change these values. In any case, it is probably also unsafe to assume that nothing else can change these values ​​while your program is running without the knowledge of the user.

Although there are always exceptions, I would say that in general, a program that exceeds these limits should review its code. Limitations exist for some reason, and almost all other pieces of software on your system work within these limits without any problems. Do you really need many files to open at the same time, or would it be easier to open several files, process them, close them and open several more? Is your library / program trying to do too much in one large package, or would it be better to break it down into smaller independent parts that work together? Do you exceed stack limits because you use a deeply recursive algorithm that can be rewritten in non-recursive mode? There are many ways in which a library and program can be improved to make it easier to change system resource limits.

+7
source

In Darwin, the standard soft limit on the number of open files is 256; the default hard drive is not limited.

AFAICR, on Solaris, the default soft limit for open files is 16384, and the hard limit is 32768.

Darwin has soft / hard limits of 8192/65536 KB for stack sizes. I forgot that the limit on Solaris (and my Solaris machine is unavailable - power outages in Poughkeepsie, NY means that I cannot get to the VPN to access the car in Kansas from my home in California), but that’s essential.

I would not worry about hard limits. If I thought that 256 file descriptors could end in the library, I would increase the soft limit on Darwin; I would not worry about Solaris.

Similar restrictions apply to Linux and AIX. I can not answer for Windows.

A sad story: a few years ago I deleted code that changed the maximum file size in a program because it has not been changed since 2 MB was a large file (and on some systems there was a soft limit of only 0.5 MB). Once a decade and a few years ago, it actually increased the limit; when it was removed, it was annoying because it reduced the limit. Tempus fugit and all that.


On SuSE Linux (SLES 10), open file limits are 4096/4096, and stack limits are 8192 / no limit.

+1
source

Short answer: it is normal, but not inflexible . Of course, there are restrictions to prevent rogue or starving users of the resource system. Desktop systems will be less restrictive than server systems, but still have certain limitations (for example, file descriptors.)

This does not mean that restrictions cannot be changed using constant / reproducible manners, either by the user at the discretion of the user (for example, by adding the appropriate ulimit calls to .profile ) or programmatically from programs / libraries that know with certainty what they will need a large number of file descriptors (for example, setsysinfo (SSI_FD_NEWMAX, ...) ), a stack (provided at the time pthread was created), etc.

+1
source

Since you need to support a large number of different systems, I would consider it appropriate to configure some well-known values ​​of good values ​​for system limits / resources, since the default values ​​can vary greatly between systems.

The default size for pthread stacks is, for example, such a case. Recently, I had to find out that the default value for HPUX11.31 is 256 KB (!), Which is not very reasonable, at least for our applications.

Setting well-defined values ​​increases the portability of the application, since you can be sure that on each platform there are X file descriptors, Y stack size ... on all platforms, and that it’s not just good luck.

I have a tendency to set such restrictions from the program itself, since the user has fewer things that need to be messed up (someone is always trying to run a binary without a shell script). To further enable runtime environment variables, one could use to override the default values ​​(while still observing the minimum limits).

+1
source

Let's look at it like this. It is not very convenient for customers to require customers to set these restrictions. As indicated in other answers, you are likely to fall into soft limits, and they can be changed. Thus, change them automatically, if necessary, in a script that will run the actual application (you can even write it so that it crashes if the hard limits are too low and create a nice error message instead of segfault).

This is the practical part of it. Not knowing what the application does, I’m a little guessing, but in most cases you should not approach any of the default limits (even less progressive) of operating systems. Assuming the system is not a request bombardment server (hence a large number of files / sockets are used), this is probably a sign of sloppy programming. Based on my experience with programmers, I would suggest that file descriptors remain open for files that are only read / write once, or that the system saves an open file descriptor in a file that only changes / reads from time to time.

As for stack sizes, this can mean two things. The standard reason for a program terminating from the stack is excessive recursion (or unlimited recursion), which is a condition of an error on which restrictions are actually intended. Secondly, some large (probably configurable) structures are allocated on the stack, which should be allocated in cumulus memory. It can be even worse, and these huge structures are passed by value (instead of reference), and this will mean a big hit on the available (lost) stack spaces, as well as a large penalty for performance.

+1
source

A quick tip: if you plan to run the application on top of a 64-bit processor, then please be careful with installing stacksize unlimited. Which on a 64-bit Linux system gives -1 as stacking.

Thanks Shyam

0
source

Perhaps you could add anything that suits the start of the script, for example, 'ulimit -n -S 4096'.

But, working with Solaris since version 2.6, it is not uncommon to change rlim_fd_cur and rlim_fd_max in / etc / system forever. In older versions of Solaris, they are too small for some workloads, such as running web servers.

0
source

Source: https://habr.com/ru/post/1302572/


All Articles