How to Modify Default File Descriptor Limits (nofile ulimit) in macOS 10.5 for High-Connection Applications


2 views

When testing network-intensive applications on macOS Leopard (10.5), developers often hit the default file descriptor limit of 256. This becomes particularly problematic when:

  • Stress-testing server applications
  • Running high-concurrency benchmarks
  • Developing scalable network services

Unlike Linux systems that use /etc/security/limits.conf, macOS implements limits differently. The key components are:

// Check current limits in terminal:
$ ulimit -a
// Specifically for open files:
$ ulimit -n

For persistent changes, modify the system's launchd configuration:

#!/bin/bash
# Create or modify /etc/launchd.conf
echo "limit maxfiles 65536 65536" | sudo tee -a /etc/launchd.conf

After making changes, you'll need to reboot. For verification:

$ sysctl kern.maxfiles
$ sysctl kern.maxfilesperproc

For temporary increases during development sessions:

# Raise limit for current shell session
ulimit -n 4096

# Alternatively, run application with custom limits
launchctl limit maxfiles 65536

For daemons or background services, create a custom plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.your.app</string>
    <key>ProgramArguments</key>
    <array>
        <string>/path/to/your/app</string>
    </array>
    <key>SoftResourceLimits</key>
    <dict>
        <key>NumberOfFiles</key>
        <integer>65536</integer>
    </dict>
</dict>
</plist>

Create a test script to verify your changes:

#!/usr/bin/perl
# filetest.pl
use IO::Handle;

my @handles;
for (my $i=0; $i<1000; $i++) {
    open($handles[$i], '>', "/tmp/testfile.$i") 
        or die "Failed at $i: $!";
    print {$handles[$i]} "test";
}

If you're coming from a Linux background like Debian where /etc/security/limits.conf handles ulimits, macOS's approach will seem puzzling. The default 256 file descriptor limit (nofile) often isn't enough for development or server applications.

Unlike Linux, macOS stores these settings in:

/etc/launchd.conf
/etc/sysctl.conf

But on modern macOS versions, you'll need to create a launchd property list file instead.

Create or edit this file (requires sudo):

sudo nano /Library/LaunchDaemons/limit.maxfiles.plist

Add this configuration:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>limit.maxfiles</string>
    <key>ProgramArguments</key>
    <array>
        <string>launchctl</string>
        <string>limit</string>
        <string>maxfiles</string>
        <string>65536</string>
        <string>65536</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
    <key>ServiceIPC</key>
    <false/>
</dict>
</plist>

After creating the file:

sudo chown root:wheel /Library/LaunchDaemons/limit.maxfiles.plist
sudo chmod 644 /Library/LaunchDaemons/limit.maxfiles.plist
sudo launchctl load -w /Library/LaunchDaemons/limit.maxfiles.plist

Check your current limits with:

ulimit -n
launchctl limit maxfiles

Both should now report your new higher limit (65536 in our example).

For quick testing without reboot:

ulimit -n 65536

But this only affects the current shell session.

MacOS has hard upper limits defined at kernel level. Check them with:

sysctl kern.maxfiles
sysctl kern.maxfilesperproc

To increase these, edit /etc/sysctl.conf (create if doesn't exist):

kern.maxfiles=1048576
kern.maxfilesperproc=1048576

1. All users share these limits on macOS
2. Requires reboot for kernel-level changes
3. The launchd method persists across updates