A few months ago, I received a highly-anticipated 2020 32GB, 2.3 GHz Quad-Core Intel Core i7 MacBook Pro. Highly-anticipated because I already had one stolen (a 2019 version) earlier last year in a robbery in an AirBnB apartment I was renting while I was staying in Barcelona. It was quite a dramatic story but I won’t get into the details. This is a tech blog after all.
Back to the new computer I acquired, the thing was flying. I could open large projects in IntelliJ and VSCode, run a Kunernetes cluster using
minikube and endless amounts of terminals simultaneously on different workspaces and the thing would not miss a beat.
Within the first week of receiving machine, I got a notification indicating that there was a system update. I never had any fears come with system updates. I always found myself jumping ship and hoping no regressions or new issues are introduced upon upgrades/updates. I’m not a skeptic, I believe Apple’s QA is up to the highest testing standards.
Anyway, I let the update run for a few hours and after a couple of restarts, the OS was back up and could work on the machine again.
Pretty soon thereafter, I heard the machine fan working intensively and the low-carbon aluminum enclosure was excessively hot. I also noticed that I the interaction with the OS and applications was crawlingly-slow. I even had the machine crash 2-3 times! I decided I had enough and that it was time to put on my Sherlock Holmes hat and start the investigation.
Finding the Culprit Process
It makes sense that the first place to review would be Activity Monitor. It allows us to check the amount of energy each running process is utilizing in addition to CPU cycles and RAM allocation. Below is the screenshot of what I saw after launching Activity Monitor:
We can see that the top process,
ZscalerTunnel was really using up the CPU. I knew what this process belonged to (a VPN service). I was able to fix the
ZscalerTunnel CPU hog by installing the latest version of the application and restarting the machine. But the second process,
corespeechd was not letting go and was at times using between 3 to 4 CPUs (300-400%). And the worst part was that I had no idea what
corespeechd was (aside from a guess that it was some sort of daemon because of the letter ‘d’ in the suffix).
This question was hard to find online. I believe because I am not a registered Apple developer, I could not see any relevant documentation about this process/service. What I did find was that many people had a problem with this daemon hogging machine resources such as massive network utilization (1) and massive network utilization (2). And I also found a lot of people experiencing the high CPU consumption and on Twitter as well.
According to the online research, all fingers were pointing to one feature: Siri. In addition, all recommendations to mitigate this issue mentioned disabling/enabling or turning off Siri completely. Unfortunately for me,
corespeechd was still causing problems after my attempt to disable Siri.
Since the machine had crashed a few times, I decided the next step would be to review the system crash report.
What I found was that the OS crashed because of a segmentation fault:
Crashed Thread: 0 Dispatch queue: com.apple.main-thread Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Codes: KERN_INVALID_ADDRESS at 0x0000000108745050 Exception Note: EXC_CORPSE_NOTIFY Termination Signal: Segmentation fault: 11 Termination Reason: Namespace SIGNAL, Code 0xb Terminating Process: exc handler  Thread 0 Crashed:: Dispatch queue: com.apple.main-thread 0 libobjc.A.dylib 0x00007fff202639af objc_release + 15 1 com.apple.CoreFoundation 0x00007fff20478a76 -[__NSDictionaryI dealloc] + 146 2 libobjc.A.dylib 0x00007fff2028139d AutoreleasePoolPage::releaseUntil(objc_object**) + 167 3 libobjc.A.dylib 0x00007fff2026433e objc_autoreleasePoolPop + 161 4 com.apple.CoreFoundation 0x00007fff2047e1f0 _CFAutoreleasePoolPop + 22 5 com.apple.CoreFoundation 0x00007fff20587748 __CFRunLoopPerCalloutARPEnd + 41 6 com.apple.CoreFoundation 0x00007fff204bc88b __CFRunLoopRun + 2788 7 com.apple.CoreFoundation 0x00007fff204bb6ce CFRunLoopRunSpecific + 563 8 com.apple.Foundation 0x00007fff21248fa1 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 212 9 com.apple.Foundation 0x00007fff212d7384 -[NSRunLoop(NSRunLoop) run] + 76 10 com.apple.authorizationhost 0x0000000108661727 main + 302 11 libdyld.dylib 0x00007fff203e0621 start + 1
What was immediately visible was that there were instructions in memory address
0x00007fff20478a76 that were being allocated by the
com.apple.CoreFoundation package. This gave me the evidence I needed that tied the system crash to the issues witnessed by the
I decided to run
strace so I could see what system calls the process was executing during run-time. I found the following output indicating there was some permission issues attempting to access a certain process probe:
dtrace: error on enabled probe ID 2378 (ID 918: syscall::kevent_id:return): invalid user access in action #5 at DIF offset 0 dtrace: error on enabled probe ID 2385 (ID 904: syscall::workq_kernreturn:return): invalid user access in action #5 at DIF offset 0
launchctl to Disable
Since Siri was already off, I was pretty sure that if I found a way to completely disable
corespeechd, I would be able to release the daemon from eating up my processors.
I am familiar with using
init.d on Linux to be able to control system services. On Windows I usually just use the
Stop-Service PowerShell cmdlet. But for Mac I wasn’t sure what command line tool needs to be used. I found out that the preferred way is to use
I also wanted to understand where MacOS startup scripts are stored. I found out that there were 5 different directories:
/System/Library/LaunchDaemons/– System-wide daemons provided by the operating system.
/System/Library/LaunchAgents/– Per-user agents provided by the operating system.
~/Library/LaunchAgents/– Per-user agents provided by the user.
/Library/LaunchAgents/– Per-user agents provided by the administrator.
/Library/LaunchDaemons/– System-wide daemons provided by the administrator.
launchd manages the processes, both for the system as a whole and for individual users using configuration files with the
I reviewed the
launchctl man page and found that we can disable a service by using the
unload command, for example:
sudo launchctl unload -w com.apple.corespeechd
That looked great! The
corespeechd daemon was no longer running and my CPU was back to normal consumption. Unfortunately, I realized my celebrations were premature when I restarted my machine.
corespeechd was back up and feasting on my machine resources again.
I went back to the
launchctl man page and found that there was another option,
remove, that could do the trick as it seemed to perform a persistent disabling of services (unlike the
unload operation which was temporary until system restart relaunched all daemons). The problem was that I was unable to run the command:
sudo launchctl remove com.apple.corespeechd
because the operating system had System Integrity Protection (SIP) enabled. I found that I could use the
csrutil command-line tool to interact with SIP. To interact with SIP, we need to go into Recovery Mode.
tl;dr , these are the steps I took to completely disable
1) Reboot the machine.
2) Press and hold Command + R.
3) Once the Recovery menu loads up, in the top menu bar, select Utilities > Terminal.
4) Run the following command to disable System Integrity Protection (SIP):
You should see the following message to acknowledge that SIP was actually disabled:
System Integrity Protection status: disabled.
5) Reboot the machine.
6) When OS loads, open a Terminal and run the following command to disable
sudo launchctl remove com.apple.corespeechd