Fixing the forking error in OS X Catalina

2020-01-17

I recently updated my operating system to OS X 10.15, Catalina. After a couple days I noticed that periodically I would return to my computer and wifi would be seemingly unavailable, and that any shell command would fail with the error

fork: Resource temporarily unavailable

If you google around for this issue, you quickly find that it's a common occurrence on MacOS. The proximate cause of this message is that your machine has reached the configured process count limit. People have suggested raising the maximum process count, which I definitely suggest you also do. However, if you are running into this problem only now after upgrading to Catalina, it is likely due to a bug introduced in the system's cron handler.

Indeed, I have a cron job set to run every minute, which, I thought, cleans up after itself and doesn't fork any long-lived processes. Grepping ps aux for the processes which that cron job invokes didn't turn up anything. However, it seems that in Catalina the parent cron process itself is sticking around:

[jack:/Users/jack] () >> ps aux | rg cron
root              3304   0.0  0.0  4308616    668   ??  S     8:41AM   0:00.00 /usr/sbin/cron
root              2485   0.0  0.0  4316808    656   ??  S     8:40AM   0:00.00 /usr/sbin/cron
root              2443   0.0  0.0  4308616    660   ??  S     8:39AM   0:00.00 /usr/sbin/cron
root              2429   0.0  0.0  4308616    668   ??  S     8:38AM   0:00.00 /usr/sbin/cron
root              2383   0.0  0.0  4316808    656   ??  S     8:37AM   0:00.00 /usr/sbin/cron
root              2298   0.0  0.0  4316808    656   ??  S     8:36AM   0:00.00 /usr/sbin/cron
root               346   0.0  0.0  4316808    668   ??  S     8:35AM   0:00.00 /usr/sbin/cron
root               269   0.0  0.0  4307596    996   ??  Ss    8:34AM   0:00.01 /usr/sbin/cron
root              9541   0.0  0.0        0      0   ??  Z     8:43AM   0:00.00 (cron)
root              9314   0.0  0.0        0      0   ??  Z     8:42AM   0:00.00 (cron)
root              3311   0.0  0.0        0      0   ??  Z     8:41AM   0:00.00 (cron)
root              2492   0.0  0.0        0      0   ??  Z     8:40AM   0:00.00 (cron)
root              2450   0.0  0.0        0      0   ??  Z     8:39AM   0:00.00 (cron)
root              2436   0.0  0.0        0      0   ??  Z     8:38AM   0:00.00 (cron)
root              2390   0.0  0.0        0      0   ??  Z     8:37AM   0:00.00 (cron)
root              2305   0.0  0.0        0      0   ??  Z     8:36AM   0:00.00 (cron)

As suggested in a comment on one of the posts linked above, redirecting the output of the cron task to /dev/null does seem to fix the problem:

[jack:/Users/jack] () >> crontab -l
- * * * * * ~/dotfiles/unison/sync-everything.sh
+ * * * * * ~/dotfiles/unison/sync-everything.sh > /dev/null 2>&1

A side effect of this is that you will not receive system emails with the output of your cron task. In my humble opinion, though, you should configure sendmail or a similar program to send a customized message to an email inbox that you actually check. For example, the cron job I have running here sends me an email when unison fails for some reason.