The case of the recursive symlink: an iTunes outlook
On a regular Friday afternoon, I pop in my iPhone to do the regular iTunes backup (like any sane person does). It turns out iTunes is instantly crashing when I try to do a backup.
That's not good news.
Trying a couple of times, but still failing, crashes right before I try to do a backup.
Now to give some context on my setup, since I'm using a 128GB iPhone, it's not the best use of storage to backup this mammoth on the primary SSD. I use a symlink approach to point my Backup folder to an external HDD.
First thing I try: as they always say, have you tried turning it off and on again?. I restart the Mac, start clean, no open apps and let's see.
Crash report analysis
Still crashes. Looking at the crash report doesn't give you a hint right away.
Process: iTunes [2360]
Path: /Applications/iTunes.app/Contents/MacOS/iTunes
Identifier: com.apple.iTunes
Version: 12.9.4 (12.9.4)
Build Info: iTunes-1200012009004094~15
Code Type: X86-64 (Native)
Parent Process: ??? [1]
Responsible: iTunes [2360]
User ID: 502
Date/Time: 2019-07-12 23:47:10.284 +0100
OS Version: Mac OS X 10.14.4 (18E226)
Report Version: 12
Anonymous UUID: <MASKED>
Time Awake Since Boot: 840 seconds
System Integrity Protection: enabled
Crashed Thread: 21
Exception Type: EXC_BAD_ACCESS (SIGBUS)
Exception Codes: KERN_PROTECTION_FAILURE at 0x000070000e218ff8
Exception Note: EXC_CORPSE_NOTIFY
Termination Signal: Bus error: 10
Termination Reason: Namespace SIGNAL, Code 0xa
Terminating Process: exc handler [2360]
Seems that iTunes is trying to access something it's not supposed to?
First thing comes to suspicion is the symlink. Maybe some folder structure changed or the symlink broke for some reason (drive name change, etc..).
I delete the /Library/Application Support/MobileSync/Backup
symlink just to be sure. Guess what? Still crashes.
Looking further down through the crash report,
Thread 21 Crashed:
0 libsystem_platform.dylib 0x00007fff69140271 _platform_strlcpy + 23
1 libsystem_c.dylib 0x00007fff6902223e realpath$DARWIN_EXTSN + 291
2 com.apple.iTunes 0x000000010f23eb8e 0x10e906000 + 9669518
3 com.apple.iTunes 0x000000010f23dbd0 0x10e906000 + 9665488
...
Now _platform_strlcpy is darwin's strlcpy C function which (you guessed it) copies a string. Now what is iTunes trying to copy and failing?
My suspicion starts to go to any recently installed apps that might conflict with iTunes, I have recently installed MalwareBytes after the busy month of June Malware festival that was happening. Could it be that MalwareBytes is attempting to "scan" iTunes and causes it to crash?
Spolier alert, uninstalling MalwareBytes does not solve the issue.
Upgrading MacOS
Glancing through hoakley's MacOS 10.14.4's known bug list, it seems there are some that have issues with the APFS file system. Maybe that's it?
Upgrading to Mojave 10.14.5 does not solve the iTunes crash. So maybe 10.14.4 corrupted the filesystem somehow, let's run First Aid.
First Aid reports some directory failed checks that it is not able to solve.
Checking snapshot 1 of 6.
error: directory valence check: directory (oid 0x13): nchildren (1) does not match drec count (0)
warning: snapshot fsroot tree corruptions are not repaired; they'll go away once the snapshot is deleted
error: directory valence check: directory (oid 0x150045): nchildren (2) does not match drec count (0)
error: directory valence check: directory (oid 0x150063): nchildren (2) does not match drec count (0)
...
Now I've dealt with corrupted disks before and trust me, it ain't fun. Literally anything and everything can go wrong with a corrupted filesystem and it becomes near impossible to debug.
So before giving up and reformatting, I decided to give it another shot, what else can go wrong?
To eliminate variables as much as possible, I try loading up iTunes on a different User Account. Guess what? It works perfectly fine.
We got a lead!
It now seems that my user has some kind of corrupted settings that iTunes cannot access. Now let's get rid of anything user related that iTunes would access and it should work, right?
Still crashing, iTunes recreates these settings files and crashes shortly after navigating to the iOS device tab.
At this point I was on the verge of giving up and just popping in the Time Machine and going back to when it was working, but that is rather a destructive solution that would not solve the root cause (which will probably return and haunt me again).
Another less-destructive solution would be to just create a new user and continue life there, but still the bug might return.
Dig deeper, debugging tools
Xcode
Debugging in Xcode was quite interesting, iTunes did not crash when attached to the debugger. This is probably due to Xcode cutting the process some slack when it comes to stack allocations (as we will see below)
fs_usage
A very useful debugging tool I use is fs_usage, it watches the process manipulate files in the filesystem and enables you to track down what's really going on. It can be very useful if you are suspicious of a process and want to know what it's doing behind the scenes.
sudo fs_usage iTunes
LO AND BEHOLD!
Right before iTunes crashes, it's trying to access these files:
Now what does iTunes have to do with this directory? Why is it trying to access PokeMMO's Application Support?
PokeMMO is an Unofficial Online Multiplayer Pokemon game that I was really hesitant when installing. It's closed source and seemed shady. (Turns out I was right, kinda?)
As you can see in the screenshot, it's trying to access the same directory, over and over again, around 200,000+ times. This is absurd!
Right before this massive recursion or loop:
/Users/ahmedshehata 0.000004 iTunes.184583
14:42:26.798987 getattrlist /Users/ahmedshehata/Pictures 0.000004 iTunes.184583
14:42:26.798992 getattrlist /Users/ahmedshehata/Pictures/PokeMMO Screenshots
It looks like iTunes is accessing the /Pictures
directory (probably to get sync data for photos synced with the iOS Device).
Looking at the /Pictures
directory and this is where we finally find our culprit. A rouge recursive symlink that has been causing iTunes to crash.
The filesystem calls to list the Pictures directory was probably causing the stack to overflow when listing through this recursive symlink.
Now recursive symlinks are no fun, they can break apps randomly, cause the SSD to wear out and cause lots of horrible things to happen.
Deleting the symlink solves the issue as expected.
I hope you have learned some useful debugging skills that can help you find the root cause of some undefined behaviour of a program without resorting to extreme measures (such as re-installing Operating System or recovering).
TLDR: PokeMMO creates a recursive symlink in
/Pictures
directory that caused iTunes to behave abnormally and crash.
Thanks for reading and let me know in the comments if you have faced a similar situation and used some cool debugging tools yourself!