Discussion:
Mac OS X and setrlimit(2)
Axel Luttgens
2013-03-21 11:59:38 UTC
Permalink
Hello,

(Not sure whether the postfix-devel list is the right place for such matters; please let me know if another place, for example the postfix-users list, would be more suitable)

Starting with Mac OS X 10.5, the man page for setrlimit(2) comes with following compatibility section:

setrlimit() now returns with errno set to EINVAL in places that
historically succeeded. It no longer accepts "rlim_cur = RLIM_INFINITY"
for RLIM_NOFILE. Use "rlim_cur = min(OPEN_MAX, rlim_max)".

As a result, a call such as open_limit(INT_MAX) from src/util/events.c may fail and hinder the master process to start.

This is a quick and dirty "fix" tested with Postfix 2.10.0 on Mac OS X 10.8.3:

--- src/util/open_limit.c.original 1998-12-11 19:55:29.000000000 +0100
+++ src/util/open_limit.c 2013-03-21 11:57:05.000000000 +0100
@@ -63,6 +63,9 @@
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return (-1);
if (limit > 0) {
+#ifdef MACOSX
+ if (limit > OPEN_MAX) limit = OPEN_MAX;
+#endif
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else

I don't know whether such restrictions on admissible values for rlim_cur are liable to occur on other OSes as well.

Axel
Wietse Venema
2013-03-21 12:58:03 UTC
Permalink
Post by Axel Luttgens
Hello,
(Not sure whether the postfix-devel list is the right place for
such matters; please let me know if another place, for example the
postfix-users list, would be more suitable)
The place is OK.
Post by Axel Luttgens
Starting with Mac OS X 10.5, the man page for setrlimit(2) comes
setrlimit() now returns with errno set to EINVAL in places that
historically succeeded. It no longer accepts "rlim_cur = RLIM_INFINITY"
for RLIM_NOFILE. Use "rlim_cur = min(OPEN_MAX, rlim_max)".
Postfix does not ask for RLIM_INFINITY file descriptors (if someone
modified Postfix, you should bug the guilty party instead).

How can this code:

if (limit > 0) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else
rl.rlim_cur = limit;
setrlimit(RLIMIT_NOFILE, &rl)

produce an error for any "limit" value > 0? Does rlim_max contain
a value that is not allowed for rlim_cur? That would warrant a MacOS
bugreport, as the rlim_max value came from the MacOS system itself,
not from Postfix.

Please print the rlim_max value and report it on the list.

This would need to be verified before I will make any code changes
for Postfix.
Post by Axel Luttgens
+#ifdef MACOSX
+ if (limit > OPEN_MAX) limit = OPEN_MAX;
+#endif
Assuming that the above problem is real, your solution would seriously
cripple Postfix. OPEN_MAX is a constant; it is a lower bound (a
measly 64 on FreeBSD which sits under much of MacOS).

Such a tiny number may be OK for simple apps but not for Postfix
which needs to be able to scale up with real hardware.

I think a better solution would be based on sysconf(_SC_OPEN_MAX)
which reflects the true system limit.

if (limit > 0) {
long sysconf_limit;

sysconf_limit = sysconf(_SC_OPEN_MAX);
if (sysconf_limit < 0)
return (-1);
if (limit > sysconf_limit)
limit = real_limit;
...

That way we have an authoritative estimate of what the system
can do for Postfix.

Wietse
Axel Luttgens
2013-03-21 15:04:17 UTC
Permalink
Post by Wietse Venema
Post by Axel Luttgens
Hello,
(Not sure whether the postfix-devel list is the right place for
such matters; please let me know if another place, for example the
postfix-users list, would be more suitable)
The place is OK.
Post by Axel Luttgens
Starting with Mac OS X 10.5, the man page for setrlimit(2) comes
setrlimit() now returns with errno set to EINVAL in places that
historically succeeded. It no longer accepts "rlim_cur = RLIM_INFINITY"
for RLIM_NOFILE. Use "rlim_cur = min(OPEN_MAX, rlim_max)".
Postfix does not ask for RLIM_INFINITY file descriptors (if someone
modified Postfix, you should bug the guilty party instead).
Well... I started with the source code of Postfix 2.10.0 as downloaded from one of the official mirrors (ftp://ftp.easynet.be/postfix/index.html).
I hope "they" didn't made a mess of it. ;-)
Post by Wietse Venema
if (limit > 0) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else
rl.rlim_cur = limit;
setrlimit(RLIMIT_NOFILE, &rl)
produce an error for any "limit" value > 0? Does rlim_max contain
a value that is not allowed for rlim_cur? That would warrant a MacOS
bugreport, as the rlim_max value came from the MacOS system itself,
not from Postfix.
More precisely, the problem seems to be related to allowable values for rlim_cur: INT_MAX doesn't seem to belong to that set.

But agreed: the man page might deserve some rewriting.
Post by Wietse Venema
Please print the rlim_max value and report it on the list.
Just after the "if (limit > 0)" test, the values are:

limit: 2147483647, rl.rlim_cur: 256, rl.rlim_max: 9223372036854775807

Without the "fix", those values are before the call to setrlimit():

limit: 2147483647, rl.rlim_cur: 2147483647, rl.rlim_max: 9223372036854775807
Post by Wietse Venema
This would need to be verified before I will make any code changes
for Postfix.
Post by Axel Luttgens
+#ifdef MACOSX
+ if (limit > OPEN_MAX) limit = OPEN_MAX;
+#endif
while they are, with the "fix":

limit: 10240, rl.rlim_cur: 10240, rl.rlim_max: 9223372036854775807

Calling setrlimit() with 2147483647 for rl.rlim_cur fails, but succeeds with 10240.
This is consistent with the very last sentence of the man page's compatibility section.
Post by Wietse Venema
Assuming that the above problem is real, your solution would seriously
cripple Postfix. OPEN_MAX is a constant; it is a lower bound (a
measly 64 on FreeBSD which sits under much of MacOS).
Such a tiny number may be OK for simple apps but not for Postfix
which needs to be able to scale up with real hardware.
In the case of Mac OS X, sys/syslimits.h shows:

#define OPEN_MAX 10240 /* max open files per process - todo, make a config option? */

This seems to be the value returned by "sysctl kern.maxfilesperproc":

$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 10240

I've just checked on a 10.3.9 box: this was already the case.
Post by Wietse Venema
I think a better solution would be based on sysconf(_SC_OPEN_MAX)
which reflects the true system limit.
Here, sysconf(_SC_OPEN_MAX) returns 256, which is consistent with:

$ getconf OPEN_MAX
256
$ ulimit -n
256

and which also appears to be the default value returned for rlim_cur by getrlimit().

Please do not hesitate, should you need additional info.

And thanks for your feedback,
Axel
Wietse Venema
2013-03-21 17:26:24 UTC
Permalink
Post by Axel Luttgens
Calling setrlimit() with 2147483647 for rl.rlim_cur fails, but
succeeds with 10240. This is consistent with the very last sentence
of the man page's compatibility section.
Apple does not own the getrlimit() API. It is part of a standard.
I sent the URLs in a different reply. If Apple changes their
implementation they they drop out of the standard.

To avoid confusion I'll use RLIM_INFINITY instead of INT_MAX but
we already know that it isn't going to make a difference for recent
MacOS versions.

What is the value of rlim_cur BEFORE Postfix changes it?

[OPEN_MAX=10240]
Post by Axel Luttgens
$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 10240
That is the default limit. kern.maxfilesperproc can be changed.

The OPEN_MAX=10240 constant is safe for the SMALLEST possible
configuration. Postfix should not use that.

If the system administrator configures a larger value, then Postfix
should not limit itself to the default limit.

[sysconf(_SC_OPEN_MAX)]

If sysconf(_SC_OPEN_MAX) returns the same 256 as "getconf OPEN_MAX",
then that isn't going to be useful.

What does the following program print?

-------
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_FILES_PER_PROC "kern.maxfilesperproc"

#define perrorexit(text) do { perror(text); exit(1); } while (0)

int main(int argc, char **argv)
{
int limit;
int len = sizeof(limit);

if (sysctlbyname(MAX_FILES_PER_PROC, &limit, &len,
(void *) 0, (size_t) 0) < 0)
perrorexit("sysctlbyname MAX_FILES_PER_PROC");
printf("%d\n", limit);
return (0);
}
-------

This will likely be the same as rlim_cur BEFORE Postfix changes it.

Wietse
Viktor Dukhovni
2013-03-21 19:40:15 UTC
Permalink
Post by Wietse Venema
What does the following program print?
-------
#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define MAX_FILES_PER_PROC "kern.maxfilesperproc"
#define perrorexit(text) do { perror(text); exit(1); } while (0)
int main(int argc, char **argv)
{
int limit;
int len = sizeof(limit);
if (sysctlbyname(MAX_FILES_PER_PROC, &limit, &len,
(void *) 0, (size_t) 0) < 0)
perrorexit("sysctlbyname MAX_FILES_PER_PROC");
printf("%d\n", limit);
return (0);
}
-------
After chaning "int len" to "size_t len" and "int limit" to "long limit":

#include <sys/types.h>
#include <sys/sysctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define MAX_FILES_PER_PROC "kern.maxfilesperproc"

#define perrorexit(text) do { perror(text); exit(1); } while (0)

int main(int argc, char **argv)
{
long limit;
int len = sizeof(limit);

if (sysctlbyname(MAX_FILES_PER_PROC, &limit, &len,
(void *) 0, (size_t) 0) < 0)
perrorexit("sysctlbyname MAX_FILES_PER_PROC");
printf("%ld\n", limit);
return (0);
}

it compiles and prints "10240". After running:

# sysctl -w kern.maxfilesperproc=10241

it prints "10241".

--
Viktor.
Axel Luttgens
2013-03-21 19:43:12 UTC
Permalink
Post by Wietse Venema
Post by Axel Luttgens
Calling setrlimit() with 2147483647 for rl.rlim_cur fails, but
succeeds with 10240. This is consistent with the very last sentence
of the man page's compatibility section.
Apple does not own the getrlimit() API. It is part of a standard.
I sent the URLs in a different reply. If Apple changes their
implementation they they drop out of the standard.
Damn... all of this started with such a seemingly innocuous detail... :-(
Anyway, please refer to my other post as far as a possible bug report to Apple is concerned.
Post by Wietse Venema
To avoid confusion I'll use RLIM_INFINITY instead of INT_MAX but
we already know that it isn't going to make a difference for recent
MacOS versions.
Yes, probably...
Post by Wietse Venema
What is the value of rlim_cur BEFORE Postfix changes it?
Unless I made a mistake, it is 256.
From my previous post:

Just after the "if (limit > 0)" test, the values are:

limit: 2147483647, rl.rlim_cur: 256, rl.rlim_max: 9223372036854775807
Post by Wietse Venema
[OPEN_MAX=10240]
Post by Axel Luttgens
$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 10240
That is the default limit. kern.maxfilesperproc can be changed.
The OPEN_MAX=10240 constant is safe for the SMALLEST possible
configuration. Postfix should not use that.
If the system administrator configures a larger value, then Postfix
should not limit itself to the default limit.
[sysconf(_SC_OPEN_MAX)]
If sysconf(_SC_OPEN_MAX) returns the same 256 as "getconf OPEN_MAX",
then that isn't going to be useful.
What does the following program print?
-------
[...]
-------
I had to change "int len = ..." into "size_t len = ..." so as to avoid a warning.
The ouput is: 10240.

Thanks again,
Axel
Wietse Venema
2013-03-21 14:02:23 UTC
Permalink
Post by Wietse Venema
Post by Axel Luttgens
Hello,
(Not sure whether the postfix-devel list is the right place for
such matters; please let me know if another place, for example the
postfix-users list, would be more suitable)
The place is OK.
Post by Axel Luttgens
Starting with Mac OS X 10.5, the man page for setrlimit(2) comes
setrlimit() now returns with errno set to EINVAL in places that
historically succeeded. It no longer accepts "rlim_cur = RLIM_INFINITY"
for RLIM_NOFILE. Use "rlim_cur = min(OPEN_MAX, rlim_max)".
You might want to file a MacOS bug report. According to SUSV2 (Single
UNIX Specification, Version 2, from 1997)

Specifying RLIM_INFINITY as any resource limit value on a
successful call to setrlimit() inhibits enforcement of that
resource limit.

http://pubs.opengroup.org/onlinepubs/7908799/xsh/getrlimit.html

Open Group Base Specifications Issue 6 IEEE Std 1003.1, 2004 Edition:

Specifying RLIM_INFINITY as any resource limit value on a
successful call to setrlimit() shall inhibit enforcement of
that resource limit.

http://pubs.opengroup.org/onlinepubs/009696799/functions/getrlimit.html

Based on this I think that a conforming setrlimit() implementation
must accept RLIM_INFINITY as "any resource limit value". resource
limit value.

Wietse
Post by Wietse Venema
Postfix does not ask for RLIM_INFINITY file descriptors (if someone
modified Postfix, you should bug the guilty party instead).
if (limit > 0) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else
rl.rlim_cur = limit;
setrlimit(RLIMIT_NOFILE, &rl)
produce an error for any "limit" value > 0? Does rlim_max contain
a value that is not allowed for rlim_cur? That would warrant a MacOS
bugreport, as the rlim_max value came from the MacOS system itself,
not from Postfix.
Please print the rlim_max value and report it on the list.
This would need to be verified before I will make any code changes
for Postfix.
Post by Axel Luttgens
+#ifdef MACOSX
+ if (limit > OPEN_MAX) limit = OPEN_MAX;
+#endif
Assuming that the above problem is real, your solution would seriously
cripple Postfix. OPEN_MAX is a constant; it is a lower bound (a
measly 64 on FreeBSD which sits under much of MacOS).
Such a tiny number may be OK for simple apps but not for Postfix
which needs to be able to scale up with real hardware.
I think a better solution would be based on sysconf(_SC_OPEN_MAX)
which reflects the true system limit.
if (limit > 0) {
long sysconf_limit;
sysconf_limit = sysconf(_SC_OPEN_MAX);
if (sysconf_limit < 0)
return (-1);
if (limit > sysconf_limit)
limit = real_limit;
...
That way we have an authoritative estimate of what the system
can do for Postfix.
Wietse
Axel Luttgens
2013-03-21 17:47:38 UTC
Permalink
Post by Wietse Venema
[...]
You might want to file a MacOS bug report. According to SUSV2 (Single
UNIX Specification, Version 2, from 1997)
Specifying RLIM_INFINITY as any resource limit value on a
successful call to setrlimit() inhibits enforcement of that
resource limit.
http://pubs.opengroup.org/onlinepubs/7908799/xsh/getrlimit.html
Specifying RLIM_INFINITY as any resource limit value on a
successful call to setrlimit() shall inhibit enforcement of
that resource limit.
http://pubs.opengroup.org/onlinepubs/009696799/functions/getrlimit.html
Based on this I think that a conforming setrlimit() implementation
must accept RLIM_INFINITY as "any resource limit value". resource
limit value.
Hello Wietse,

Strictly speaking, I'm not sure one could validly file a bug report in this case:

- setrlimit() is described as being part of the XSI extension,
- Apple indeed claims conformance to POSIX 1003.1, but not to the XSI extension
- moreover, Apple's man page for setrlimit() doesn't refer to any standard
- and anyway, the standard describes what should happen after a successful call to setrlimit(), but remains silent about the case of an unsuccessful call.

But this is just my poor understanding of such matters... ;-)

Axel
Wietse Venema
2013-03-21 19:38:35 UTC
Permalink
Axel Luttgens:
[default open file rlim_max = 9223372036854775807]

Thanks for doing the experiments. On 64-bit systems the number
9223372036854775807 equals RLIM_INFINITY. This implies that
MacOS X does not enforce the open file limit.

This rlim_max value breaks a heuristic that Postfix uses to increase
the number of open files to the hard limit (Postfix expects that
rlim_max will always be smaller than INT_MAX, and tries to set the
current (rlim_cur) limit to no more than that value).

Below is a patch that fixes the heuristic. When the system reports
an RLIM_INFINITY hard limit for the number of open files, there is
no need for Postfix to update the open file limit, because it is
not enforced.

Please give this a try, and report if this cures the problem.

BTW looks like this file hasn't changed in a long time.

Wietse

*** src/util/open_limit.c- Fri Dec 11 13:55:29 1998
--- src/util/open_limit.c Thu Mar 21 15:28:49 2013
***************
*** 62,68 ****
#ifdef RLIMIT_NOFILE
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return (-1);
! if (limit > 0) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else
--- 62,69 ----
#ifdef RLIMIT_NOFILE
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return (-1);
! /* Don't update the limit when it is not enforced. */
! if (limit > 0 && rl.rlim_max != RLIM_INFINITY) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else
Viktor Dukhovni
2013-03-21 22:20:29 UTC
Permalink
Post by Wietse Venema
[default open file rlim_max = 9223372036854775807]
Thanks for doing the experiments. On 64-bit systems the number
9223372036854775807 equals RLIM_INFINITY.
An interesting API choice, since file descriptors larger than
INT_MAX cannot be used with open(2), close(2), read(2), write(2), ...
So using a 64-bit (long) limit for a 32-bit (int) quantity is a
bit perverse.
--
Viktor.
Wietse Venema
2013-03-21 23:18:15 UTC
Permalink
Post by Viktor Dukhovni
Post by Wietse Venema
[default open file rlim_max = 9223372036854775807]
Thanks for doing the experiments. On 64-bit systems the number
9223372036854775807 equals RLIM_INFINITY.
An interesting API choice, since file descriptors larger than
INT_MAX cannot be used with open(2), close(2), read(2), write(2), ...
So using a 64-bit (long) limit for a 32-bit (int) quantity is a
bit perverse.
setrlimit() handles limits other that file handles, and
all limits use RLIM_INFINITY to indicate "no enforcement".

Wietse
Axel Luttgens
2013-03-22 09:48:34 UTC
Permalink
Post by Wietse Venema
[default open file rlim_max = 9223372036854775807]
Thanks for doing the experiments. On 64-bit systems the number
9223372036854775807 equals RLIM_INFINITY. This implies that
MacOS X does not enforce the open file limit.
This rlim_max value breaks a heuristic that Postfix uses to increase
the number of open files to the hard limit (Postfix expects that
rlim_max will always be smaller than INT_MAX, and tries to set the
current (rlim_cur) limit to no more than that value).
Below is a patch that fixes the heuristic. When the system reports
an RLIM_INFINITY hard limit for the number of open files, there is
no need for Postfix to update the open file limit, because it is
not enforced.
Hello Wietse,

Thanks for having provided the rationale behind the checks.
Post by Wietse Venema
Please give this a try, and report if this cures the problem.
So, to be sure I am in sync, this is the change I've introduced in open_limit.c:

--- src/util/open_limit.c.original 1998-12-11 19:55:29.000000000 +0100
+++ src/util/open_limit.c 2013-03-22 08:56:07.000000000 +0100
@@ -62,7 +62,8 @@
#ifdef RLIMIT_NOFILE
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return (-1);
- if (limit > 0) {
+ /* Don't update the limit when it is not enforced. */
+ if (limit > 0 && rl.rlim_max != RLIM_INFINITY) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else

This indeed allows a successful launch of master, qmgr...

But this leaves us with a rather low soft limit (rlim_cur) of 256 descriptors by default in the case of Mac OS X. Doesn't this come with potential problems?

And, kind of thought experiment: what if Apple later decides to set a bound hard limit by default, instead of an unbound one?
Post by Wietse Venema
BTW looks like this file hasn't changed in a long time.
Yes, 1998! Quite impressive... ;-)

Axel
Wietse Venema
2013-03-22 10:55:21 UTC
Permalink
Post by Axel Luttgens
--- src/util/open_limit.c.original 1998-12-11 19:55:29.000000000 +0100
+++ src/util/open_limit.c 2013-03-22 08:56:07.000000000 +0100
@@ -62,7 +62,8 @@
#ifdef RLIMIT_NOFILE
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return (-1);
- if (limit > 0) {
+ /* Don't update the limit when it is not enforced. */
+ if (limit > 0 && rl.rlim_max != RLIM_INFINITY) {
if (limit > rl.rlim_max)
rl.rlim_cur = rl.rlim_max;
else
This indeed allows a successful launch of master, qmgr...
But this leaves us with a rather low soft limit (rlim_cur) of 256
descriptors by default in the case of Mac OS X. Doesn't this come
with potential problems?
You are mistaken. First, since rlim_max==RLIM_INFINITY the limit is
not enforced (unless Apple totally screwed up the setrlimit() API).
Second, rlim_cur was 256 because YOUR patch changed it. Third, you
could test your concern by setting a really low rlim_cur and seeing
if it is enforced while rlim_max==RLIM_INFINITY.

Wietse
Axel Luttgens
2013-03-22 11:46:45 UTC
Permalink
Post by Wietse Venema
[...]
You are mistaken. First, since rlim_max==RLIM_INFINITY the limit is
not enforced (unless Apple totally screwed up the setrlimit() API).
Hmmm... who knows?
They are very inventive, sometimes... ;-)
Post by Wietse Venema
Second, rlim_cur was 256 because YOUR patch changed it.
No no: when entering open_limit(), rlim_cur has a default value of 256.
My quick patch just raised that to OPEN_MAX indirectly, by bringing the value of parameter limit back to an "allowable" value (instead of INT_MAX).
Now, because of the test against RLIM_INFINITY, we don't touch rlim_cur anymore, which thus remains at 256.
Post by Wietse Venema
Third, you
could test your concern by setting a really low rlim_cur and seeing
if it is enforced while rlim_max==RLIM_INFINITY.
I'll probably try that one.
What limit would you chose, so as to be sure to encounter the problem if any?

Axel
Wietse Venema
2013-03-22 12:08:50 UTC
Permalink
Post by Axel Luttgens
Post by Wietse Venema
Third, you
could test your concern by setting a really low rlim_cur and seeing
if it is enforced while rlim_max==RLIM_INFINITY.
I'll probably try that one.
What limit would you chose, so as to be sure to encounter the problem if any?
master(8) opens >= 1 file handle for each master.cf entry. So you
could try that as the limit.

If rlim_cur value is enforced, as it may well be, then my next bet
is to use the sysctl() result. A hard constant value would be
fundamentally incorrect.

Wietse
Axel Luttgens
2013-03-22 18:03:47 UTC
Permalink
Post by Wietse Venema
[...]
If rlim_cur value is enforced, as it may well be, then my next bet
is to use the sysctl() result. A hard constant value would be
fundamentally incorrect.
Indeed, it is enforced; for example, with rlim_cur set to 10:

postfix/master[73696]: fatal: open /_ROOT/etc/postfix/master.cf: Too many open files

Now, could it be considered that all Postfix processes are, directly or indirectly, children of the master process? If yes, shouldn't they all inherit the limits from the master process?
In which case it could perhaps be sufficient to emit the values related to RLIMIT_NOFILE (and possibly other relevant similar settings) in the log, at master's startup.
And even propose a quick diagnostic, a bit à la Dovecot with its "Warning: fd limit (ulimit -n) is lower than required under max. load (256 < 1000), because of ..." messages.
It would then be the system administrator's responsibility to provide the right settings.

I ask, because all of this has always tended to be a mess in the Unix world: too many interfaces for handling "seemingly similar yet coming with subtle differences" entities... And the risk is great to spend much time for anyway encountering another nth edge case, one day or another.

Just musing...

Anyway, I think I'll ask (thru the bugreporter) some clarifications for that man page; without any other contextual information, that suggestion for a constant value is indeed somewhat surprising...

Axel
Wietse Venema
2013-03-22 18:16:48 UTC
Permalink
Post by Axel Luttgens
Post by Wietse Venema
If rlim_cur value is enforced, as it may well be, then my next bet
is to use the sysctl() result. A hard constant value would be
fundamentally incorrect.
postfix/master[73696]: fatal: open /_ROOT/etc/postfix/master.cf: Too many open files
[diagnostics]
Post by Axel Luttgens
And even propose a quick diagnostic, a bit ? la Dovecot with its
"Warning: fd limit (ulimit -n) is lower than required under max.
load (256 < 1000), because of ..." messages. It would then be the
system administrator's responsibility to provide the right settings.
Postfix already logs this, only the threshold is different.

I don't think that sysadmins should suffer because Apple has 10240
in the per-process kernel limit and only 256 in the rlimit structure.

On FreeBSD, from which much of Apple code is derived, the sysctl()
value is the same as the rlimit value:

$ limits
...
openfiles 11095
...
$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 11095

Hence my suggestion that Postfix use the kern.maxfilesperproc
value, as in a separate response (with code).

Wietse
Axel Luttgens
2013-03-23 12:56:51 UTC
Permalink
Post by Wietse Venema
[...]
Hence my suggestion that Postfix use the kern.maxfilesperproc
value, as in a separate response (with code).
Hello Wietse,

Intuitively, I came to that idea too.
But because all those ambiguities, and before I (perhaps) get an explanation from Apple wrt their man page, I wanted to do a quick check.

So, I wrote another quick and dirty piece of code (I know, I can't refrain):

#include <sys/resource.h>
#include <limits.h>
#include <stdio.h>
#include <sys/errno.h>

int main(int argc, char **argv)
{
int i;
struct rlimit rl;

if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
{
printf("getrlimit failed with rc=%i\n", errno);
return -1;
}

for (i = OPEN_MAX - 100; i < INT_MAX ; i++)
{
rl.rlim_cur = i;
if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
{
printf("setrlimit failed with i=%i and rc=%i\n", i, errno);
return -1;
}
}

printf("Ended with i=%i\n", i);
return 0;
}

and got those results:

$ sysctl kern.maxfilesperproc
kern.maxfilesperproc: 10240
$ ./setrlimit
setrlimit failed with i=10241 and rc=22
$ sudo sysctl -w kern.maxfilesperproc=12000
kern.maxfilesperproc: 10240 -> 12000
$ ./setrlimit
setrlimit failed with i=12001 and rc=22
$ sudo sysctl -w kern.maxfilesperproc=10240
kern.maxfilesperproc: 12000 -> 10240
$ ./setrlimit
setrlimit failed with i=10241 and rc=22

So, allowable values for rlim_cur indeed seem to be bounded by the value of kern.maxfilesperproc; this appears quite logical, should one want to have such bounds defined for the operation of setrlimit().

I guess the code of open_limit() may thus (more or less) safely be arranged around the value of kern.maxfilesperproc.

And I now have a good reason to submit a bug report: the man page is wrong. ;-)

Axel

Loading...