目次: Linux
昨日(2024年10月1日の日記参照)のUbuntu 22とxrdpの組み合わせで起きるエラーですが、VirtualBox 7.0.18で再現できるかやってみました。グラフィクスはVMSVGAを選択しています。VMSVGAは/dev/driの下にcard0とrenderD128が生成されるようです。ちなみにgdm3は終了させてxrdpのみ起動しています。
ちなみに結論から言っておくと再現しません。以下が通常時のログです。正常に画面が表示されます。
gnome-session-binary[2774]: DEBUG(+): Enabling debugging gnome-session-binary[2774]: GLib-GIO-DEBUG(+): _g_io_module_get_default: Found default implementation dconf (DConfSettingsBackend) for ‘gsettings-backend’
ログにはデバッグ有効であることと、libEGLが何かしら見つけて反応しています。それ以外は特に何も出ません。
次にcard0とrenderD128をリネームしてアクセスできないようにして試しました。しかし正常に画面が表示されます。えぇー?ログは下記のようになりました。
gnome-session-binary[4319]: DEBUG(+): Enabling debugging gnome-session-check-accelerated: GL Helper exited with code 512 libEGL warning: DRI2: failed to authenticate gnome-session-check-accelerated: GLES Helper exited with code 512 gnome-session-binary[4319]: GLib-GIO-DEBUG(+): _g_io_module_get_default: Found default implementation dconf (DConfSettingsBackend) for ‘gsettings-backend’
AMDのGPUでも見かけたfailed to authenticateが出ています。が、エラーは無視されるんでしょうか?謎の動きですね。
目次: Linux
WindowsからUbuntu 22.04 LTSのxrdpに接続すると真っ黒な画面しか出ず、すぐに接続が切断されてしまう問題に遭遇しました。どこでクラッシュしているか調べるため、xrdpがGNOMEを起動するところまでを追いかけると下記のようになっていました。
/etc/xrdp/startwm.sh exec /bin/sh /etc/X11/Xsession /etc/X11/Xsession.d/99x11-common_start /usr/bin/ssh-agent /usr/bin/im-launch x-session-manager /usr/bin/x-session-manager /usr/libexec/gnome-session-binary
スクリプトx-session-managerを書き換えてgnome-session-binaryの引数に--debugを足すと、GNOMEはより詳細なメッセージを出力します。メッセージはホームディレクトリの.xsession-errorsに記録されます。GNOMEのエラーメッセージは下記です。
** (gnome-session-check-accelerated-gles-helper:3301100): WARNING **: 13:50:04.884: eglInitialize() failed gnome-session-check-accelerated: GLES Helper exited with code 256 gnome-session-binary[3300977]: DEBUG(+): hardware acceleration check failed: Child process exited with code 1 gnome-session-binary[3300977]: GLib-DEBUG(+): setenv()/putenv() are not thread-safe and should not be used after threads are created gnome-session-binary[3300977]: GLib-DEBUG(+): posix_spawn avoided (fd close requested) gnome-session-is-accelerated: No hardware 3D support. gnome-session-check-accelerated: GL Helper exited with code 256 ★★ここでエラーが発生している amdgpu_device_initialize: amdgpu_get_auth (1) failed (-1) amdgpu_device_initialize: amdgpu_get_auth (1) failed (-1) ** (gnome-session-check-accelerated-gles-helper:3301174): WARNING **: 13:50:09.927: eglInitialize() failed gnome-session-check-accelerated: GLES Helper exited with code 256 gnome-session-binary[3300977]: WARNING: software acceleration check failed: Child process exited with code 1 gnome-session-binary[3300977]: CRITICAL: We failed, but the fail whale is dead. Sorry....
エラーメッセージ曰くamdgpu_get_auth()が失敗しています。関数名から推測するにAMDのGPUが装着されているマシンでしか発生しないエラーなのかもしれません。この関数は何者なのかDRMのソースコード(Mesa/libdrmのソースコードリポジトリへのリンク)を見ると、
// drm/amdgpu/amdgpu_device.c
/**
* Get the authenticated form fd,
*
* \param fd - \c [in] File descriptor for AMD GPU device
* \param auth - \c [out] Pointer to output the fd is authenticated or not
* A render node fd, output auth = 0
* A legacy fd, get the authenticated for compatibility root
*
* \return 0 on success\n
* >0 - AMD specific error code\n
* <0 - Negative POSIX Error code
*/
static int amdgpu_get_auth(int fd, int *auth)
{
int r = 0;
drm_client_t client = {};
if (drmGetNodeTypeFromFd(fd) == DRM_NODE_RENDER)
*auth = 0;
else {
client.idx = 0;
r = drmIoctl(fd, DRM_IOCTL_GET_CLIENT, &client); //★★エラーを返すのはこの関数だけ★★
if (!r)
*auth = client.auth;
}
return r;
}
// drm/xf86drm.c
/**
* Call ioctl, restarting if it is interrupted
*/
drm_public int
drmIoctl(int fd, unsigned long request, void *arg)
{
int ret;
do {
ret = ioctl(fd, request, arg); //★★drmIoctl()はioctl()が返すエラーをそのまま返す★★
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
return ret;
}
ソースコードから推測するにグラフィクス系のデバイスファイルにioctl()しようとして失敗しているものと思われます。
XのグラフィックスはDRI(Direct Rendering Infrastructure)と呼ばれるインタフェースを経由してGPUを使用します。Xとカーネルの間にはlibDRMがおり、libDRMはLinuxカーネルのDRM(Direct Rendering Manager)を使用してGPUにアクセスします。DRMのデバイスファイルは/dev/driディレクトリの下にありますが、名前がDRIだったりDRMだったりして謎ですね。グラフィクス周りはあまり詳しくなくて理由はわかりません……。
# ls /dev/dri/* -la crw-rw-rw-+ 1 root video 226, 0 4月 30 15:00 /dev/dri/card0 crw-rw-rw-+ 1 root render 226, 128 4月 30 15:00 /dev/dri/renderD128
上記のようにキャラクタデバイス/dev/dri/card0と/dev/dri/renderD128のパーミッションを0666にしたところエラーが出なくなりました。今回はこの2つのデバイスファイルで解決しましたが、他のデバイスファイルにもアクセスしていた場合はさらに調査が必要かもしれません。グラフィクス系のエラーは簡単に調べる方法がないのが辛いですね。
ちなみにこの症状はQEMUだと再現しません。card0のパーミッションを0000にするとlibEGLがエラーになるのですが、なぜかGNOMEはエラーを無視して起動してしまいます。AMDのときだけなんで止まるんでしょうか。いまいち釈然としません……。
クラッキングでぶっ壊されてしまったニコニコ動画が復活し、シン・ニコニコ動画になって帰ってきました。いちユーザーとしては嬉しい気分でいっぱいです。
しかし前と比べて困ったことが起きていて、BizHawkで出力した動画をシン・ニコニコ動画にアップロードしようとすると「この動画の映像形式には対応していません」とエラーが出てしまって投稿できません。試行錯誤の末、解決方法を見つけたのでメモしておきます。
端的に言えば原因はピクセルフォーマットでした。BizHawkは特に何も言わないとYUV444で出力しますが、ニコニコ動画はYUV420でないと受け付けてくれないようです。どこにもそんな制約は書いていないため、仕様か?バグか?どちらともわかりません。
YUV420にする方法ですけども、BizHawkの出力設定を[Custom]にして、下記のようにピクセルフォーマットを明示的に指定すればYUV420で出力してくれました。
-c:a aac -c:v libx264 -preset ultrafast -pix_fmt yuv420p -f mp4
もしすでにYUV444で出力済みの動画ならば、ffmpegを使って再エンコードすれば良いです。
$ ffmpeg -i input.mp4 \ -vcodec libx264 -vb 2048000 -r 60 -s 1280x720 -pix_fmt yuv420p \ -acodec aac -ar 44100 -ab 192000 output.mp4
動画ビットレート(-vb)、フレームレート(-r)、動画サイズ(-s)は元の動画に応じて調整してください。
< | 2024 | > | ||||
<< | < | 10 | > | >> | ||
日 | 月 | 火 | 水 | 木 | 金 | 土 |
- | - | 1 | 2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | - | - |
合計:
本日: