Almost a year ago, I made the switch to using Mac OS X as my primary workstation. As difficult as the transition was during my first 3 weeks, it has now become second nature to me. I haven’t had any major issues along the way, but now and then, I have had to tweak a thing or two. Here is the most recent such example.
Lately, I’ve been seeing a fair number of the following error, when launching commands under Bash within a local Terminal session. It’s rather annoying, because it stops me from getting any work done. As a systems administrator, I have lots of Terminal sessions open, and this is where the error has always manifested itself.
[laptop:~ root]$ ssh somehost -bash: fork: Resource temporarily unavailable
The first time this happened to me, I didn’t think much of it, so I rebooted my system. Today, I did not feel like rebooting my system, because I have a ton of work in progress. I suspect most people won’t hit this resource limit, but if you’re a power user, you eventually might.
Like other Unix-like operating systems, Max OS X limits the maximum number of processes, system-wide and per-user, but it does so with a rather conservative number. On my Mac, system-wide processes were limited to 512, and per-user processes were limited to 266. I’ve never encountered this problem on Linux, because these values are dynamically set in the kernel, based on the amount of memory installed in the Linux system.
Here’s how I resolved this problem.
- First, determine what your system’s current limits are. These are the values on my installation of Mac OS X 10.5 with 4 GB of RAM.
[laptop:~ root]$ sysctl -a | grep maxproc | grep =
kern.maxproc = 512
kern.maxprocperuid = 266
- Now set these to higher values. I suggest approximately doubling what you already have.
[laptop:~ root]$ sysctl -w kern.maxproc=1024 [laptop:~ root]$ sysctl -w kern.maxprocperuid=512
- You’ll also want to apply these changes automatically at system bootup. To do so, add them to the /etc/sysctl.conf file.
[laptop:~ root]$ sudo vi /etc/launchd.conf [laptop:~ root]$ cat /etc/sysctl.conf kern.maxproc=1024 kern.maxprocperuid=512
- At this point, launched processes will still inherit the default maxprocperuid value of 266. I would like to change this inherited default value for new processes automatically, but I haven’t found a way to increase the default system-wide soft-limit of maxprocperuid on Mac. On Linux, I simply update the /etc/security/limits.conf file, but I don’t see such a file under Mac OS X. If you know of a way to do this in Mac OS X, leave a comment below. For now, I’ve added the following command to my user’s .bash_profile file. The value of 512 is intended to match that of kern.maxprocperuid shown above.
ulimit -u 512
- To confirm the change, launch a new Terminal session, and run the following command. Before the change, you will have seen “266.” After the change, you should see “512”.
[laptop:~ root]$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) 6144 file size (blocks, -f) unlimited max locked memory (kbytes, -l) unlimited max memory size (kbytes, -m) unlimited open files (-n) 256 pipe size (512 bytes, -p) 1 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 512 virtual memory (kbytes, -v) unlimited
A commenter posted a link below, referring me to a method of changing the default system-wide values at boot time. I’ve elaborated in greater detail below.
My system is running a newer version of Mac OS X (10.5.8), and it uses a launchd daemon, which is the parent of all processes (similar to init under Linux). This launchd daemon can read options from a configuration file, which can be used to set the various “limit” values. There is both a system-wide and a per-user launchd daemon, and each can be configured independently, although the user’s launchd daemon will inherit its values from the system’s launchd at boot time . The system-wide daemon values will always limit the maximum values that a per-user daemon can set.
Further, the launchd daemon can be re-configured live (with certain limitations), using the launchctl command, without requiring a reboot. Though, I suggest that you add your custom settings to /etc/launchd.conf to persist your changes across reboots.
- First, check your existing user’s launchd settings. For each setting, there are two values. A “soft” limit on the left, and a “hard” limit on the right. The soft limit is the currently active limit. However, you can increase the soft limit up to (but not greater than) the hard limit. The root user can increase the hard limits of the system-wide launchd, without a reboot. However, you cannot change a user’s launchd hard limits without a reboot (even if trying to do so as the root user).
[laptop:~ user]$ launchctl limit cpu unlimited unlimited filesize unlimited unlimited data 6291456 unlimited stack 8388608 67104768 core 0 unlimited rss unlimited unlimited memlock unlimited unlimited maxproc 266 532 maxfiles 256 unlimited
- Next, check your system-wide setings. Notice how the user-specific values are identical to the system-wide settings, as they were inherited at boot time.
[laptop:~ user]$ sudo su - [laptop:~ root]$ launchctl limit cpu unlimited unlimited filesize unlimited unlimited data 6291456 unlimited stack 8388608 67104768 core 0 unlimited rss unlimited unlimited memlock unlimited unlimited maxproc 266 532 maxfiles 256 unlimited [laptop:~ root]$ exit
- If you do not need to increase the user-specific values before rebooting, then go on to the next step. Otherwise, if you need to resolve your immediate “fork: Resource temporarily unavailable” problem, try the following steps. (You may need to close some applications first.) Remember, you will not be able to increase the soft values higher than the hard limit imposed by the user’s launchd daemon. If you try to set the soft limit too high, the value will be reduced to the hard limit value. As illustrated in the example below, increasing the maxproc soft limit to 512 succeeds, while increasing the maxproc hard limit to 1024 fails. Run the following commands as the user (not root).
[laptop:~ user]$ launchctl limit maxproc 512 1024 [laptop:~ user]$ launchctl limit maxfiles 512 unlimited [laptop:~ user]$ launchctl limit cpu unlimited unlimited filesize unlimited unlimited data 6291456 unlimited stack 8388608 67104768 core 0 unlimited rss unlimited unlimited memlock unlimited unlimited maxproc 512 532 maxfiles 512 unlimited
- Now, place new system-wide default settings into the /etc/launchd.conf file. You will need to create this file, as it does not exist by default. This file contains only the options that are passed to launchctl (not the launchctl command itself). Note that on OS X 10.5.8, the maxproc value has a maximum hard limit of 2500.
[laptop:~ user]$ sudo vi /etc/launchd.conf [laptop:~ user]$ cat /etc/launchd.conf limit maxproc 1024 2048 limit maxfiles 1024 unlimited
- You may also create a configuration file at $HOME/.launchd.conf, which can be used to set the per-user values. But you need this only if you want smaller default values than what the system allows the user-specific launchd to inherit.
For additional information on launchctl settings, check out the following man pages.
[laptop:~ user]$ man launchd.conf [laptop:~ user]$ man launchctl [laptop:~ user]$ man getrlimit
Serverfault has the answer to how to increase the defaults at boot/login time: http://serverfault.com/questions/15564/where-are-the-default-ulimits-specified-on-os-x-10-5
Basically, you configure them in /etc/launchd.conf:
limit maxproc 1024 1024
Thanks for the link Logan. I hadn’t realized that launchd has its own settings file. I have taken what I found on that web page, and further elaborated on it.
This tip might help alleviate the “Potential VM growth in DirectoryService” error that plagues 10.5.x Sever. Thanks for the detailed breakdown!
Using the newer launchctl approach as per addendum above.
On my Mac OS X 10.6.7 the maxfiles cannot be unlimited (it says) but a high numeric worked.
J.