先日portsのGNOME2がごっそりとアップデートされて、gdmがgdm-2.24.1_4になったのですが、そうしたら、gdmが動かなくなってしまいました。
まず最初に気がついたのは、ローカルホスト上でXサーバを起動しようとして、コケてること。
「--debug」オプションをつけて「gdm --debug」で起動すると、いろいろメッセージが表示されるのですが、ローカルホスト上でXサーバを起動しようとしたけど失敗、それを10回くらい繰り返した後、エラーばっかだから、やめちゃうよ、といって終わってるみたいです。
gdm-binary[53863]: DEBUG(+): GdmDisplay: Unmanaging display
gdm-binary[53863]: DEBUG(+): GdmDisplay: unmanage display
gdm-binary[53863]: DEBUG(+): GdmSlaveProxy: Killing slave
gdm-binary[53863]: DEBUG(+): GdmSlaveProxy: Disposing slave proxy
gdm-binary[53863]: DEBUG(+): GdmSlaveProxy: Killing slave
gdm-binary[53863]: WARNING: GdmDisplay: display lasted 0.999561 seconds
gdm-binary[53863]: DEBUG(+): GdmLocalDisplayFactory: static display status changed: 3
gdm-binary[53863]: DEBUG(+): GdmDisplayStore: Unreffing display: 0x812ba28
gdm-binary[53863]: WARNING: GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors
そのホストはサーバー用に使っているので、もともとXサーバは動かしていませんでした。また、driかなんかの問題で、うまくXサーバが動かなかった、という理由もあります。
そういうことから、gdmがXサーバを起動しないようにするために、/usr/local/etc/gdm/custom.confの[servers]のところに、
0=inactive
と書いてありました。
gdm-2.24.1になると、この0=inactiveという記述は、考慮されなくなっているようです。
gdm-2.24のドキュメントを探しても、どうやったら0=inactiveと同じことを実現できるのか、ぜんぜんわからず、ソースコードを斜め読みまでしたんですが、よくわからず。
gdm-manager.cの、このあたりが関係しそうなんだけど。
void
gdm_manager_start (GdmManager *manager)
{
g_debug ("GdmManager: GDM starting to manage");
if (! manager->priv->wait_for_go) {
gdm_display_factory_start (GDM_DISPLAY_FACTORY (manager->priv->local_factory));
}
それから、子プロセスで、こんなのを実行しようとしてるんですよね。
/usr/local/libexec/gdm-simple-slave --display-id /org/gnome/DisplayManager/Display1
最初は、grepであたりをつけてソースコードを眺める、ということをやってたんですが、どうもよくわかんないので、portsでビルドするとき、デバッグ機能を有効にするために
# make WITH_DEBUG=yes
して、gdbでgdm-binをトレース実行までしてみたんですけど・・・
この辺を見てみたり
(gdb) where
#0 gdm_local_display_factory_new (store=0x8102e30)
at gdm-local-display-factory.c:620
#1 0x08057af1 in gdm_manager_constructor (type=135434096,
n_construct_properties=1, construct_properties=0x8114570)
at gdm-manager.c:328
#2 0x48226643 in g_object_newv () from /usr/local/lib/libgobject-2.0.so.0
#3 0x482271f1 in g_object_new_valist ()
from /usr/local/lib/libgobject-2.0.so.0
#4 0x48227360 in g_object_new () from /usr/local/lib/libgobject-2.0.so.0
#5 0x08057e63 in gdm_manager_new () at gdm-manager.c:424
#6 0x0804d8aa in main (argc=239172, argv=0x480a3200) at main.c:605
とりあえず、/usr/local/bin/Xを起動することになっているのはわかったので(これにコマンドライン引数を指定する方法はわかんなかった・・・Xserversとかいうファイルを見ないのかねぇ?)、/usr/local/bin/Xを、Xvfbを起動するラッパースクリプトに置き換えてしまいました(笑)。
Xvfbには、-verboseオプションが無いんですね。
Unrecognized option: -verbose
% cat /usr/local/bin/X
#! /bin/sh
command=$*
echo $command
command2=`echo $command | sed 's/-verbose//'`
exec /usr/local/bin/Xvfb $command2
セキュリティホールがありそうな気もしないでもないので、あくまでもテスト用。
☆
あとでまともな解決方法を考えることにして、とりあえず、これれOK・・・と思いきや、今度は、XDMCPが使えていないことに気がつきました。
ネット検索してみると、このあたりに情報がでてました。どうも、gdm-2.24でXDMCPが使えないバグがあるみたいです。
http://shirata.ddo.jp/papa/blog/2008/11/fedora10gdmxdmcpmasapatch.html
http://forums.fedoraforum.org/showthread.php?t=203674
http://bugzilla.gnome.org/show_bug.cgi?id=561396
3つめのURLのページには、1つめのページで示されたパッチは正しいようには思えない、という開発者(?)からのコメントがついています。どうやら、revision 6610のgdmで、あれこれ修正されているみたいです。
subversionってほとんど使ったことがないんですが、とりあえず、ソースコードをとりよせてみましょうか。
% svn checkout --revision 6610 http://svn.gnome.org/svn/gdm/trunk gdm
A gdm/m4
A gdm/m4/.cvsignore
A gdm/gui
A gdm/gui/user-switch-applet
A gdm/gui/user-switch-applet/gdm-user-menu-item.c
A gdm/gui/user-switch-applet/gdm-entry-menu-item.c
~~~ おぉ!でてくる、でてくる ~~~
A gdm/po/oc.po
U gdm
リビジョン 6610 をチェックアウトしました。
取り出したファイルを確認してみると・・・
% head gdm/NEWS
===============
Version 2.24.0
===============
- Allow the build to succeed without a gdm user (Frederic Peters)
- Use Bourne shell syntax in Xsession.solaris (Brian Cameron)
- Set ownership of .gconf.mandatory (William Jon McCann)
portsでインストールしたgdm-2.24.1よりも、revision 6610のほうが古いじゃん。
う~ん???よくわかんないので、2.24.1を展開して、
% tar zxf /usr/ports/distfiles/gnome2/gdm-2.24.1.tar.bz2
svnでcheckoutしたコードと差分をもとめ
% diff -ur gdm-2.24.1/daemon/ gdm/daemon/ >/tmp/gdm.diff
portsでパッチをあてるところまでやって、
# make patch
svnとの差分をパッチあてして(強引だけど、一応、これでもよさそうな雰囲気であることは確認。daemonディレクトリだけ差分をもとめたのは、docsの中がかなり違ってたので)
# cd (portsの作業ディレクトリ)/x11/gdm/work/gdm-2.24.1/daemon/
# patch -p2 < /tmp/gdm.diff
コンパイルしなおして、再インストール。
# cd /usr/ports/x11/gdm/
# make
# make install FORCE_PKG_REGISTER=yes
さて、これでgdmを実行してみると、ポート番号177が開いてたので、XDMCPが有効になっていることは確認できました。
とりあえずVNC serverを使ってXDMCPが使えているか確認。
% Xvnc :1 -query サーバ
すると、だらだら~とメッセージが表示され・・・
gdm-binary[56430]: WARNING: Unable lookup hostname: Non-recoverable failure in name resolution
gdm-binary[56430]: WARNING: Unable lookup hostname: Non-recoverable failure in name resolution
gdm-binary[56430]: WARNING: Unable lookup hostname: Non-recoverable failure in name resolution
gdm-binary[56430]: WARNING: Unable lookup hostname: Non-recoverable failure in name resolution
Illegal instruction
あらあら、gdmが、おっこちました。
gdbで落っこちるまでの動きを調べてみると・・・
(gdb) where
#0 gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfc8d8) at gdm-address.c:220
#1 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#2 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfcd78) at gdm-address.c:220
#3 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#4 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfd218) at gdm-address.c:220
#5 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#6 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfd6b8) at gdm-address.c:220
#7 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#8 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfdb58) at gdm-address.c:220
#9 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#10 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfdff8) at gdm-address.c:220
#11 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#12 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfe498) at gdm-address.c:220
#13 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#14 0x0805fbac in gdm_address_get_hostname (address=0x810710c, hostnamep=0xbfbfe938) at gdm-address.c:220
#15 0x08060526 in gdm_address_debug (address=0x810710c) at gdm-address.c:516
#16 0x0805e1fa in decode_packet (source=0x8129980, cond=G_IO_IN, factory=0x810e818) at gdm-xdmcp-display-factory.c:2840
#17 0x482bd76d in g_io_channel_unix_get_fd () from /usr/local/lib/libglib-2.0.so.0
#18 0x48289226 in g_main_context_dispatch () from /usr/local/lib/libglib-2.0.so.0
#19 0x4828c5c2 in g_main_context_check () from /usr/local/lib/libglib-2.0.so.0
#20 0x4828c9a7 in g_main_loop_run () from /usr/local/lib/libglib-2.0.so.0
#21 0x0804da50 in main (argc=1, argv=0xbfbfebc8) at main.c:639
gdm_address_debug() と gdm_address_get_hostname() が交互に呼び出されて、無限ループして、きっとスタックがあふれたんでしょう。
ソースコードを眺めてみると
gboolean
gdm_address_get_hostname (GdmAddress *address,
char **hostnamep)
{
char host [NI_MAXHOST];
int res;
gboolean ret;
g_return_val_if_fail (address != NULL || address->ss != NULL, FALSE);
ret = FALSE;
host [0] = '\0';
res = getnameinfo ((const struct sockaddr *)address->ss,
sizeof (struct sockaddr_storage),
host, sizeof (host),
NULL, 0,
0);
if (res == 0) {
ret = TRUE;
goto done;
} else {
g_warning ("Unable lookup hostname: %s", gai_strerror (res));
gdm_address_debug (address);
gdm_address_get_hostnameでエラーが出たとき、そのエラーメッセージを出すためにgdm_address_debugを呼び出すのですが・・・
void
gdm_address_debug (GdmAddress *address)
{
char *hostname;
char *host;
char *port;
g_return_if_fail (address != NULL);
hostname = NULL;
host = NULL;
port = NULL;
gdm_address_get_hostname (address, &hostname);
呼び出された先のgdm_address_debugで、また、gdm_address_get_hostnameを使ってます。
だめぢゃん・・・
とりあえずこの辺については、なんとか回避するコードを追加。
でも、やっぱり動かない。
gdmにXDMCPのリクエストが届いたとき、
res = getnameinfo ((const struct sockaddr *)address->ss,
sizeof (struct sockaddr_storage),
host, sizeof (host),
NULL, 0,
0);
みたいな感じで、リクエストの出所のアドレスを求めているんですが、なぜか、そのアドレスが正しく取り出せないんです。うちの環境の問題かなぁ?
リクエスト元がわからないので、gdmも、返事を返せず、という状況になっているようでした。
address->ssの先に、IPアドレスが埋め込まれているのはgdbで確認ずみなんですが、sockaddr_inとか、もうすっかり忘れちゃってる。どういうデータが正しいんだったかなぁ。
☆
というわけで、旧バージョンのgdmをpkg_addしちゃいました。せっかく消したgailが、またインストールされちゃいましたが・・・
svnで最新のgdmのコードを取り出して差分を眺めてみたんですが、6610とあまり変わらないんですよねぇ。
どうしたものか。
ちなみに、Xvfbの中では、gdmのログインウインドウが表示されていました。きっと、inetではなくunixドメインだから動いてるんでしょうね。