1年疑ってたMAMP+Viteの相性問題、真犯人はiCloudだった
ローカル開発中に errno=11 Resource deadlock avoided というエラーに何度も遭遇し、しばらく「MAMPとViteの相性問題」だと思い込んでいました。実際に調べてみると、原因はまったく別のところにありました。同じ構成(macOS + MAMP + ~/Documents/ 配下での開発)を踏んでいる人向けに、経緯ごと共有します。
症状
Laravel + Vite構成のプロジェクトで、突然こんなエラーが出てブラウザが真っ白になります。
Notice: require(): Read of N bytes failed with errno=11 Resource deadlock avoided
in vendor/composer/autoload_real.php on line 12
Fatal error: Uncaught Error: Failed opening required '...ClassLoader.php'
@vite() を含むBladeビューでは、こういう形で出ることもあります。
hash_file(): Read of 8192 bytes failed with errno=11 Resource deadlock avoided
at vendor/laravel/framework/src/Illuminate/Filesystem/Filesystem.php:191
ブラウザはHTTP 500。コマンドラインで composer dump-autoload を打っても、コマンド自体がハングします。
最初に疑った仮説(誤り):MAMP + Viteのデッドロック
@vite() を含むビューで出ることが多かったため、当初は「Vite の manifest 読み込みとMAMPのApacheプロセスが競合しているのでは」と考えていました。実際、npm run build でVite manifestを作り直すと症状が一時的に消えることがあり、これがこの仮説を補強しているように見えました。
しかしこれは誤りでした。npm run build はたまたまタイミングをずらしただけで、根治にはなっていなかったのです。
実際の原因:~/Documents/ 配下 + iCloud等のファイル監視
改めて調べたところ、真因はプロジェクトの置き場所でした。~/Documents/ 配下にプロジェクトを置いていると、以下のプロセスがファイルをinodeレベルで掴み続けます。
- iCloud Drive(「デスクトップと書類フォルダ」の同期)
- Google Drive の File Provider Extension(
DFSFileProviderExtension) - Time Machine のローカルスナップショット
- Spotlight のインデクサ
これらがAPFSのCOW(copy-on-write)参照を保持している状態で、Apacheの並列workerが mmap() で同じファイルを読もうとすると、カーネルが EDEADLK を返します。CLIから file_get_contents で読む分にはただの read() syscallなので普通に通りますが、Apacheのmmapアクセスとは競合パターンが違う。「CLIでは再現しないのにブラウザだけ壊れる」という不可解な挙動の正体はこれでした。
Vite自体にもMAMP自体にも非は無く、同期系サービスとApacheのファイルアクセス方式が噛み合っていなかった、というのが結論です。
対処
恒久対処:プロジェクトを同期対象外の場所に置く
/Applications/MAMP/htdocs/ 配下など、iCloud DriveやGoogle Driveの監視対象外にプロジェクトを移設するのが根本対処です。
緊急対処(引っ越せない場合)
# 1. Time Machineを止める
tmutil stopbackup
# 2. ローカルスナップショットを確認して削除
tmutil listlocalsnapshots /
tmutil deletelocalsnapshots <SNAPSHOT_ID>
# 3. それでも直らなければTime Machineの対象から除外
tmutil addexclusion /path/to/project
tmutil isexcluded /path/to/project
# 4. 最後の手段:autoloadファイルのinodeを切る
cd vendor/composer
for f in *.php; do cp -p "$f" "$f.tmp" && mv "$f.tmp" "$f"; done
# 5. MAMPのApacheをStop→Startしてoutput OPcacheをクリア
教訓
-
「直った」と「治った」は違う。
npm run buildで一時的に症状が消えたことに引っ張られて、1年近くMAMPとViteの相性問題だと誤認していました。再発した瞬間に同じ回避策を繰り返すのではなく、一度腰を据えて原因を洗い直すべきでした。 - CLIで再現しないからといって原因ではないとは言えない。Apacheのmmapアクセスと、CLIの通常readでは、同じファイルシステム上のロック競合でも挙動が変わります。
- macOSでローカル開発をするなら、プロジェクトはiCloud/Google Drive/Time Machineの監視対象外に置くのが最も安全です。
~/Documents/は便利な場所に見えて、常時監視系のサービスが集中しがちな場所でもあります。
この調査をしていたのは、フリーランス・少人数チーム向けの案件管理ツール AYUMI(歩) を開発している最中でした。よかったら覗いてみてください。