curl
メモリリーク

libcurlが使用するNSSにdentryが肥大化するバグがあった

  • ある日、壁紙みたいに表示させてるモニタリングおいて、がっつりメモリリークしてるパターンに気づく。
    image.png

  • とりあえず、アプリケーションエンジニアに状況を共有(サーバサイドも並行して調査)し、あるリリースからスタックし始めてるのでメモリリークしちゃってる箇所がないか確認してもらったけど、それっぽいところが見つからないという回答。


  • 気になる子が居た
    • こいつ、スタックし続けているぞ...
(snip)
Slab:            1955484 kB
(snip)
# slabtop -o
(snip)
  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME
9575244 9575244 100%    0.19K 455964       21   1823856K dentry
(snip)
  • クリアして様子見したけど、その後、同じ曲線を描きながらスタックし続けている。dentryはスタックするものだけど、こう短期間に値が増えるとかちょっと考えにくい
# sync && echo 2 >> /proc/sys/vm/drop_caches
Cause: The NSS did not check whether the NSS_SDB_USE_CACHE environment variable was set to trye before calling the sdb_measureAccess internal function. 
Consequence: When using curl or libcurl, which depennds on nss, to make a HTTPS requests there were many "access" system calls to paths/directories/files that do not exist, and this bloated the dentry_cache.
Fix: NSS now avoids calls to sdb_measureAccess in lib/softoken/sdb.c s_open if NSS_SDB_USE_CACHE is "yes"
Result: The system calls to non-existent paths have gone down and curl HTTPS requests not longer cause bloats in in the directory entry cache.
  • libcurlが使用するNSSにdentryが肥大化するバグがあるとのこと

    • NSSを3.16.0以降のバージョンにupdateして環境変数NSS_SDB_USE_CACHEに"YES"を記述すれば肥大化する問題は解決しそう...!
  • アプリケーションエンジニアに再度ヒアリングすると、curlを使用した機能を新たにデプロイしたとのことで、原因の90%はこれだと推測。いざ計測。

  • NSSのversion確認

    • versionは問題なさそう
$ yum list installed nss-softokn* *curl*
Loaded plugins: priorities, update-motd, upgrade-helper
15 packages excluded due to repository priority protections
Installed Packages
curl.x86_64                                                                                         7.40.0-3.52.amzn1                                                                         installed
libcurl.x86_64                                                                                      7.40.0-3.52.amzn1                                                                         installed
libcurl-devel.x86_64                                                                                7.40.0-3.52.amzn1                                                                         @amzn-updates/latest
nss-softokn.x86_64                                                                                  3.16.2.3-13.37.amzn1                                                                      @amzn-main/latest
nss-softokn-devel.x86_64                                                                            3.16.2.3-13.37.amzn1                                                                      @amzn-main/latest
nss-softokn-freebl.x86_64                                                                           3.16.2.3-13.37.amzn1                                                                      @amzn-main/latest
nss-softokn-freebl-devel.x86_64                                                                     3.16.2.3-13.37.amzn1                                                                      @amzn-main/latest
python27-pycurl.x86_64                                                                              7.19.0-17.12.amzn1                                                                        installed
  • 環境変数NSS_SDB_USE_CACHEyes記述
    • この辺はitamaeでプロビジョニングするけど、設定とかは割愛
      • 既存セッションもこの変数を使えるようにするにはサーバ再起動が手っ取り早い
(snip)
#Dentry Cache Prevention of hypertrophy
export NSS_SDB_USE_CACHE=YES
(snip)
$ env | grep NSS
NSS_SDB_USE_CACHE=YES
  • 結果
    • curlを実行してもdentryはスタックせず、その後のメモリ使用量も上昇し続けることはなくなりました。 スクリーンショット 2017-12-18 18.31.45.png