FreeBSD11.2: ラジコでrtmpdumpがコアダンプする原因判明

FreeBSD 11.2でラジコをrtmpdumpを使用するシェルスクリプトで録音しようとすると、core dump するという現象、ようやく原因がわかりました。

FreeBSD11.2でrtmpdumpでradiko.jp を録音すると、rtmpdump がコアダンプするため、サーバーOSを FreeBSD11 にアップデートすることは断念し、FreeBSD10.4で使用することにしました。
これは、サポートがあるOSを使って Radiko.jp を聞くことが出来ないのと、サポート切れOSを使用するが Radikoを聞けることのどちらが良いかの二択でした。選択は簡単で、出来ないよりも出来る方が良い訳です。不都合としては、pkgによるバイナリパッケージメンテナンスが出来ません。バイナリでは管理出来ませんが、portupgrade コマンドによりメンテナンス可能です。時間と手間は掛かりますけどね。

さて、こういう背景で運営しているサーバーですが、先日 portupgradeコマンドによりパッケージをメンテナンスしました。ffmpegやrtmpdumpは更新対象から外すように pkg lock を掛けています。従って rtmpdump が更新されることはないのですが、なんと、radiko.jp の自動録音に失敗していました!

rtmpdump が core を吐いて落ちてました。私が慌てふためいた途中経過は省略して、core をデバッガーで開いてみると、次の通り。

gdb /usr/local/bin/rtmpdump rtmpdump.core
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "amd64-marcel-freebsd"...(no debugging symbols found)...
Core was generated by `rtmpdump -v -r rtmpe://f-radiko.smartstream.ne.jp/ --playpath simul-stream.strea'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/local/lib/librtmp.so.1...(no debugging symbols found)...done.
Loaded symbols for /usr/local/lib/librtmp.so.1
Reading symbols from /usr/lib/libssl.so.7...(no debugging symbols found)...done.
Loaded symbols for /usr/lib/libssl.so.7
Reading symbols from /lib/libcrypto.so.7...(no debugging symbols found)...done.
Loaded symbols for /lib/libcrypto.so.7
Reading symbols from /lib/libz.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libz.so.6
Reading symbols from /lib/libc.so.7...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.7
Reading symbols from /libexec/ld-elf.so.1...(no debugging symbols found)...done.
Loaded symbols for /libexec/ld-elf.so.1
#0  0x0000000800dbf007 in EVP_MD_CTX_init () from /lib/libcrypto.so.7
(gdb) bt
#0  0x0000000800dbf007 in EVP_MD_CTX_init () from /lib/libcrypto.so.7
#1  0x0000000800db6342 in HMAC_CTX_init () from /lib/libcrypto.so.7
#2  0x00000008008360e4 in RTMP_Write () from /usr/local/lib/librtmp.so.1
#3  0x000000080082d62a in RTMP_Connect1 () from /usr/local/lib/librtmp.so.1
#4  0x000000080082e819 in RTMP_Connect () from /usr/local/lib/librtmp.so.1
#5  0x0000000000403b6a in ?? ()
#6  0x000000000040191f in ?? ()
#7  0x0000000800627000 in ?? ()
#8  0x0000000000000000 in ?? ()

この結果、FreeBSD11.2 と同じじゃない?!!!!!!

ということは、rtmpdump の core dump は、portupgradeによるソースからビルドで更新インストールされたパッケージの中に原因がある訳です。

履歴を確認してみたところ、見つかりました。

Feb  5 22:39:32 host pkg: librtmp-2.4.20151223 deinstalled
Feb  5 22:39:34 host pkg-static: librtmp-2.4.20151223_3 installed

librtmpdump が 2.4.20151223 → 2.4.20151223_3 とアンダーバー付きのマイナーバージョンアップされたことが原因だと判明。

幸い FreeBSD10.4用のバイナリーパッケージはメンテナンスされていないため、librtmp-2.4.20151223 がそのまま残っています。

pkg delete で librtmp を削除した後、pkg install でもう一度入れれば解決します。
正確には、librtmp は rtmpdump との依存関係があるので、一度 rtmpdump のロックを解除し、librtmp と rtmpdump を入れ直した後、rtmpdump と librtmp をロックしました。

FreeBSD10.4 上では、これで一応の回避完了。
FreeBSD11.2 上では、原因は判明したものの、librtmp-2.4.20151223 を入れる方法が、現時点では、10.4からOSごと上げる方法しか思いつきません。

radikoシェルスクリプトをステップ実行すると、libcrypto, librtmp あたりでcoreダンプしているので、radikoサーバーとSSL通信しようとしてこけているらしいことはわかっていましたが、librtmp を旧バージョンにするか、libcrypto(こっちはOSに含まれる)が修正されれば FreeBSD11以上でも解決しそうです。

FreeBSD11.2 上での回避策

先日 rtmpdump と radikoシェルスクリプトの動作確認を行ったFreeBSD 10.4 VM環境が残っているので、このVMを使って11.2での radiko録音環境をどう作るかを確認してみました。

  1. まず、rtmpdump, librtmp, ffmpeg をインストールした後、これらのパッケージをpkg lock でロックします。
  2. freebsd-update -r 11.2-RELEASE upgrade コマンドで 10.4→11.2 へアップグレードします。
  3. OSだけアップデートすれば、radikoシェルスクリプト動作環境は10.4のまま固定されるので録音可能な環境は維持できます。
  4. しかし、その他のパッケージは、10.4用バイナリなので、厳密には11.2の環境とミスマッチです。そこで、pkg upgrade を使ってパッケージをバイナリアップデートします。
  5. この後、rtmpdumpで録音しようとすると、
    authentication success
    areaid: JP13
    Shared object "libssl.so.7" not found, required by "rtmpdump"
    

    というエラーが発生。

  6. エラーメッセージを検索してみたところ、次のヒントが見つかりました。
    https://zandronum.com/forum/viewtopic.php?t=7892
    libssl.so.8 とシンボリックリンクすれば良さそうです。
    /usr/lib の下で、

    # ln -s libssl.so.8 libssl.so.7

    を実行。

  7. そうすると、今度は
    authentication success
    areaid: JP13
    Shared object "libcrypto.so.7" not found, required by "rtmpdump"

    となったため、/lib の下で、

     # ln -s libcrypto.so.8 libcrypto.so.7

    と実行。

  8. その後、rtmpdumpにて録音を試みたところエラーなく録音出来ました。

それぞれのライブラリには一応互換性があるようです。

FreeBSD 11.2 をクリーンインストールした後 rtmpdump を使えるようにするには

rtmpdump と librtmp は依存関係にあり、インストールや削除しようとすると一緒に処理されてしまいます。
FreeBSD11.2の場合は、パッケージサーバー上にあるバイナリーが、

  • rtmpduump-2.4.20151223
  • librtmp-2.4.20151223_3

の組み合わせであることが問題の一つ。
もう一つが、rtmpdump が必要とする /usr/lib/libssl.so.7 と /lib/libcrypto.so.7 がバージョンアップ済みで存在しないこと。これが二つめの問題。
これらを回避できれば、radikoシェルスクリプトが FreeBSD11.2上で復活します。libssl と libcrypto に関してはシンボリックリンクで回避できました。(上記6,7)

librtmp に関しては、FreeBSD 10.4 上でlibrtmp-2.4.20151223 パッケージを作成し、これをFreeBSD11.2に転送し、強制インストールすることにより使用できることが確認できました。

librtmp-2.4.20151223 がインストールされているホストで、

pkg create librtmp

でパッケージを作ります。パッケージはコマンドを発行したディレクトリに作成されます。

/tmp> pkg create librtmp
Creating package for librtmp-2.4.20151223
/tmp> ll lib*
-rw-r--r--  1 root  wheel  78096  2月  7 20:50 librtmp-2.4.20151223.txz
/tmp> tar ztvf librtmp-2.4.20151223.txz 
-rw-r--r--  0 root   wheel     504  1月  1  1970 +COMPACT_MANIFEST
-rw-r--r--  0 root   wheel    1917  1月  1  1970 +MANIFEST
-rw-r--r--  0 root   wheel    5622  1月 12  2017 /usr/local/include/librtmp/amf.h
-rw-r--r--  0 root   wheel    1637  1月 12  2017 /usr/local/include/librtmp/http.h
-rw-r--r--  0 root   wheel    2221  1月 12  2017 /usr/local/include/librtmp/log.h
-rw-r--r--  0 root   wheel   10967  1月 12  2017 /usr/local/include/librtmp/rtmp.h
-rw-r--r--  0 root   wheel  139254  1月 12  2017 /usr/local/lib/librtmp.a
lrwxr-xr-x  0 root   wheel       0  1月 12  2017 /usr/local/lib/librtmp.so -> librtmp.so.1
-r--r--r--  0 root   wheel  106600  1月 12  2017 /usr/local/lib/librtmp.so.1
-rw-r--r--  0 root   wheel     285  1月 12  2017 /usr/local/libdata/pkgconfig/librtmp.pc
-rw-r--r--  0 root   wheel    3076  1月 12  2017 /usr/local/man/man3/librtmp.3.gz
-rw-r--r--  0 root   wheel   18092  1月 12  2017 /usr/local/share/licenses/librtmp-2.4.20151223/GPLv2
-rw-r--r--  0 root   wheel      81  1月 12  2017 /usr/local/share/licenses/librtmp-2.4.20151223/LICENSE
-rw-r--r--  0 root   wheel     212  1月 12  2017 /usr/local/share/licenses/librtmp-2.4.20151223/catalog.mk

-f オプション付きの pkg コマンドで、_3付きの librtmp を削除した後、

# pkg delete -f librtmp

10.4で作成してコピーした、旧バージョンの librtmp パッケージをインストール。

# pkg install librtmp-2.4.20151223.txz

これとシンボリックリンクでラジコ録音が復活することを確認できましたが、課題は librtmp-2.4.20151223.txz をどう維持するかということになります。

さて、FreeBSD11.2 で Radiko録音スクリプトがcoreを吐いて動作しなかった問題の回避策が見つかりました。サポート切れ状態で使い続けている 10.4から 11.2に上げるかどうか!?
回避策で使い続けるというのは、ちょっと落ち着きませんね〜。

コメントを残す