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.