0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

1年疑ってたMAMP+Viteの相性問題、真犯人はiCloudだった

0
Posted at

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(歩) を開発している最中でした。よかったら覗いてみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?