[Armadillo:08794] Re: 起動実行と手動実行で取得する時刻がJSTとUTCで変わる

Yasuhisa Nakamura email@hidden
2013年 5月 15日 (水) 02:33:20 JST


中村@自己レスです。

結論を先に書いておきます。
ftpdでJSTにならない理由がわかりました。
busyboxのinetdのバグだと思います。

まず、訂正から。

[Armadillo:08789]で、
> init -> inet.d -> ftpd と起動されるどこかで
> タイムゾーンを設定してftpdに教えてあげれば
> ようさそうに思いますが・・・

と書きましたが、これは間違いでした。

init -> inet.d -> ftpd ではなくて、
init -> rc -> inet.d -> ftpd ですね。
あわてて書いて間違えました。

とすると、rcで export TZ=JST-9 しているのでinet.dには
TZが伝わっているはずなのに、なぜftpdには伝わらないのか?
これが問題です。

以下、ちょっと長くなりますが、せっかくなので
調査の方法も含めて結論まで書いておきます。

rcからinetdを起動したときにinetdに渡した環境変数は、
  /proc/{pid}/environ
で調べることができます。

実際にArmadillo-420でやってみるとこうなってました。
# cat /proc/778/environ
USER=rootHOME=/TERM=vt102PATH=/bin:/sbin:/usr/bin:/usr/sbinSHELL=/bin/shPWD=/TZ=JST-9

次に、inetdから起動されるコマンドでの環境変数を調べます。

方法は簡単です。
/etc/inetd.confのtelnetを次のように書き換えて、inetdに
SIGHUPを送ります。

telnet  stream  tcp  wait  root  /usr/bin/env  env

外部からtelnetでつなぐと、次のようになりました。

$ telnet 192.168.0.100
Trying 192.168.0.100...
Connected to 192.168.0.100.
Escape character is '^]'.
inetd_dummy=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Connection closed by foreign host.

inetd_dummy以外、環境変数が何もありません。

ここからは、inetdのソース調査です。
inetd.cにこんなコードがありました。
INETD_FEATURE_ENABLEDのとき、environ を書き換えてます。

extern int inetd_main(int argc, char *argv[])
{
        ...
#ifdef INETD_FEATURE_ENABLED
        extern char **environ;
        ...
        Argv = argv;
        if (environ == 0 || *environ == 0)
                environ = argv;
        while (*environ)
                environ++;
        LastArg = environ[-1] + strlen(environ[-1]);
#endif
        ...

INETD_FEATURE_ENABLEDは何かというと、これはビルトインの
echoサーバやtimeサーバなどをenableにしたときdefineされます。

そこで、make config でbuzyboxのinetdの設定を変更してみます。
 [*] inetd
 [ ] inetd: Support chargen service
 [ ] inetd: Support daytime service
 [ ] inetd: Support discard service
 [ ] inetd: Support echo service
 [ ] inetd: Support time service

これをビルドして、上のtelnetでのenv表示をやってみると
次のようになり、/proc/{pid}/environ の結果と一致します。
(増えたinetd_dummy以外は)

$ telnet 192.168.0.100
Trying 192.168.0.100...
Connected to 192.168.0.100.
Escape character is '^]'.
USER=root
HOME=/
TERM=vt102
PATH=/bin:/sbin:/usr/bin:/usr/sbin
SHELL=/bin/sh
PWD=/
TZ=JST-9
inetd_dummy=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Connection closed by foreign host.

この状態でftpでアクセスしてみると、lsでのタイムスタンプは
ちゃんとJSTになります。

ビルトインサーバを使うかどうかで environ を書き換えるか
どうかが違う(起動した子プロセスに渡される環境変数が
クリアされるかどうかが変わる)のですけど、これは
バグだと思います。

次のように書き換えたところ、ビルトインのサーバをONしていても、
引き継いだ環境変数はinetdの子プロセスに渡されるようになり、
ftpでのタイムスタンプもJSTになるようになりました。

--- inetd.c-orig        2012-12-28 11:30:59.000000000 +0900
+++ inetd.c     2013-05-15 01:36:25.000000000 +0900
@@ -744,6 +744,7 @@

 #ifdef INETD_FEATURE_ENABLED
        extern char **environ;
+       char **env = environ;
 #endif

        gid = getgid();
@@ -751,11 +752,11 @@

 #ifdef INETD_FEATURE_ENABLED
        Argv = argv;
-       if (environ == 0 || *environ == 0)
-               environ = argv;
-       while (*environ)
-               environ++;
-       LastArg = environ[-1] + strlen(environ[-1]);
+       if (env == 0 || *env == 0)
+               env = argv;
+       while (*env)
+               env++;
+       LastArg = env[-1] + strlen(env[-1]);
 #endif

 #if defined(__uClinux__)

以上です。

-- 
なかむら




armadillo メーリングリストの案内