There have been many proposed solutions to this. You can, for instance, in your shell startup scripts override the limit for that shell instance, and you can run more than 100 processes from that shell, but when you launch a new window, the parent process that launches all apps for you in the GUI is still limited to that 100 process per user limit, and the new window will fail to launch your shell. It usually fails with the error: login: fork: Resource temporarily unavailable.
There are two phases to fixing this problem. First you must change the overall OS limits for maxproc and maxprocperuid to higher values, and then you must make WindowServer run in an environment with the limits raised.
[robg adds: I have not tested this one, nor do I intend to! If you're going to experiment with it, I recommend you have a good backup first, just in case...]
System Wide
OS X 10.3 now supports the standard /etc/sysctl.conf. This means you can just put new values into this file and reboot. This is what the file looks like:
% cat /etc/sysctl.conf <br>
# Turn up maxproc <br>
kern.maxproc=2048 <br>
# Turn up the maxproc per user <br>
kern.maxprocperuid=512 <br>
Daemons /etc/rc.commonAll of the daemons that are started via /System/Library/StartupItems are started with the default maxproxperuid of 100. This might not normally be a problem, as root may not run a ton of processes, but it does matter when sshd is started up. On OS X, sshd is started out of xinetd. A quick way to affect the environment of xinetd, and all other daemons as well, is to put ulimit -u 512 at the top of /etc/rc.common. If you preferred, you could just edit the startup script for xinetd instead, which is in /System -> Library -> StartupItems -> IPServices -> IPServices.
Here is a snippet of the top of my /etc/rc.common file:
#######################
# Configure the shell #
#######################
ulimit -u 512
##
# Be strict
##
WindowServerEvery process you run from the GUI is launched by WindowServer. So we need to make WindowServer launch in such a way that it has its limits raised. I cannot determine what actually launches WindowServer. Its parent process is mach_init, and I can find no way to modify how it is launched directly. You can, however, write a wrapper script for WindowServer. This is a shell script that is launched instead of WindowServer itself which sets the limits properly, then launches the original WindowServer as normal.
- Become root on command line.
-
% cd /System/Library/Frameworks/ % cd ApplicationServices.framework/Frameworks/ % cd CoreGraphics.framework/Resources/
robg adds: Yes, you can do that as one long cd command; I snipped it apart for narrower display width.
- Type mv WindowServer WindowServer.orig
- Type vi WindowServer ... below is the script I used; the last two lines should be entered as one long line with no extra spaces in it:
#!/bin/zsh ulimit -u 384 /System/Library/Frameworks/ApplicationServices.framework/ Frameworks/CoreGraphics.framework/Resources/WindowServer.orig $*
- Type chmod a+rx WindowServer
- Type reboot
To quickly test if my solution was working I ran a bunch of sleep0 processes in the background. This was able to reproduce the problem for me on demand before the fix. I'd open one shell window, launch over 100 sleeps, and then try to launch a new Terminal window, and it would fail. After the fix, it works.

