川口です
FreeBSD + kterm において stty の設定が
起動のさせかたによっておかしくなる(?)点があるという指摘がありました.
FreeBSD の terminal 周りの問題ではないか,という
話もあるのですが,私ではよく分からないため,
識者のご意見を伺いたいとおもっています.
具体的問題点:
* kterm にて stty の min の値が通常 1 のところが0 にて起動されることがある
= アプリケーションによっては polling が無限ループ的な動作になる
即ち,CPU を 100% 使ってしまうということがある
(そのせいで ports/japanese/ng が特定の状況で 暴走 するようです)
# 後ろに(ご本人に許可を頂きましたので)
# 富田さんによって調べて頂いた内容のメールをつけます.
要点だけ記します:
* FreeBSD にて ssh 経由で kterm を起動すると stty が min = 0 で起動されてしまう
* (min = 0 なところから起動した kterm も min = 0 を引き継ぐ)
* min = 0 では特定の tty なアプリケーションが暴走する
* rxvt などは ssh 経由でも min = 0 にはならないらしい
* Linux 等では ssh 経由でも当該現象は起きない
さて,ng 自体にて本現象を回避することは出来る(*)ようなのですが
そもそも,この FreeBSD における kterm/xterm の挙動 は
おかしいのでしょうか? おかしいなら何がいけないのでしょう?
何が 本当の悪原因 なのか,また,直すべきなら何を直すべきなのでしょう?
(私ではその辺り(stty とか)の判断がそもそもよく分からないので)
よろしくお願い致します.
-- -- -- -- -- -- -- --
(*) ng のバージョンによってはそもそも問題は起きない
◆ 参考1: 富田さんによる PR
PR title: kterm, stty -a shows min = 0. this should be min = 1
http://www.FreeBSD.org/cgi/query-pr.cgi?pr=92184
(時間が経ってしまっているのは私の方で対応をすっかり忘れていたことによります)
◆ 参考2:
japanese/ng,ng-devel 関連では本件の影響(stty min 0 な状況での問題)は:
- ng 1.4.4(ng) は暴走
- ng 1.5b1(ng-devel) は普通
という感じです.
◆ 参考3: TOMITA Yoshinori さんからのメール:
なお、stty minの値の意味ですが、non-blocking readするときに、minで指定し
た値の文字数だけ読み込んだらreadが完了する、というものです。
くわしくはtermios(4)のNoncanonical Mode Input Processingに説明されています。
普通、標準入力からデータを読み込むプログラムを実行すると、Enterキーを押
すまで、read()やfread()が帰ってきませんが、ngのようなフルスクリーンエ
ディタの場合、そんな動作をされたらエディタとして使い物になりませんから
(Enterキーを押すまで入力した文字が見えない・・・)、端末の設定を変更し
て、押したキーの値を瞬時に読み出せるモード(non-canonical mode)にします。
min=0の場合は、キーを押してなくても、read()は、読み出したデータ量=0とい
うことですぐに帰ってきます。そのため、いわゆるbusy loop状態が発生して、
キーを読み出すだけの処理が全速力で実行されて、CPUタイムを消費します。
min=1ならば、少なくとも、キーを1つ押すまでは、read()が帰ってこないので、
busy loopにはなりません。
個人的な見解ですが、これはktermの問題であって、ngの問題ではないと思いま
す。xtermではやっている処理をktermはやっていないためです。VMINパラメータ
を初期化せずにnon-canonical modeにするngは、おかしいことはおかしいのです
が、japanese/ngはかなり古いプログラムですし、japanese/ng-develでは修正さ
れているようなので、ま、いいかな?と・・・(japanese/ngのほうは、どこを
直していいのかさえ、わかりませんでした)。
私は、かなり昔からFreeBSDとngを使っていたのですが、ngがCPUを100%消費する
この問題に気がついたのは、ごく最近のことです。 FreeBSDの、ターミナル関係
のライブラリが変更されたか、ssh(後述)の挙動が変更されたかのために、こ
の挙動がおきるようになったのかな?と予想はしているのですが、きっかけが何
だったのかは、いまだわかりません。
さて、min=0になる問題ですが、今、正しい再現方法がわかりました。
PR用に、英語にしておきます。
kterm and xterm will inherit the current terminal setting where k(x)term
invoked.
% stty min 123
% kterm
(in newly opened kterm window)
% stty -a
speed 9600 baud; 30 rows; 80 columns;
lflags: icanon isig iexten echo echoe echok echoke -echonl echoctl
-echoprt -altwerase -noflsh -tostop -flusho pendin -nokerninfo
-extproc
iflags: -istrip icrnl -inlcr -igncr ixon -ixoff ixany imaxbel -ignbrk
brkint -inpck -ignpar -parmrk
oflags: opost onlcr -ocrnl -oxtabs -onocr -onlret
cflags: cread cs8 -parenb -parodd hupcl -clocal -cstopb -crtscts -dsrflow
-dtrflow -mdmbuf
cchars: discard = ^O; dsusp = ^Y; eof = ^D; eol = undef;
eol2 = undef; erase = ^H; erase2 = ^H; intr = ^?; kill = ^U;
lnext = ^V; min = 123; quit = ^\; reprint = ^R; start = ^Q;
status = ^T; stop = ^S; susp = ^Z; time = 0; werase = ^W;
So, if the current terminal is MIN=0, any new kterm window will be MIN=0.
Where the first kterm got MIN=0 ?
The key was ssh.
You can reproduce like this.
% ssh SOMEHOST kterm -display MYHOST:0
In this case, ssh will not allocate pseudo-tty. kterm cannot inherit
terminal setting and it results in MIN=0.
By the way, you can forcibly allocate ptty with ssh -t
% ssh -t SOMEHOST kterm -display MYHOST:0
will be MIN=1
xterm works fine because in main.c you will see
d_tio.c_cc[VMIN] = 1;
this initialize the parameter MIN=1.
I think this is a bugf of kterm and a FreeBSD-local patch againt
japanese/ng is not good idea.
I confirmed this patch for kterm works fine for me. This is very short
patch than one attached in PR.
*** main.c Wed Apr 19 11:15:39 2006
--- /tmp/main.c Wed Apr 19 11:15:28 2006
***
*** 1405,1410
--- 1405,1411
d_tio.c_cc[VQUIT] = CQUIT; /* '^\' */
d_tio.c_cc[VEOF] = CEOF; /* '^D' */
d_tio.c_cc[VEOL] = CEOL; /* '^@' */
+ d_tio.c_cc[VMIN] = 1;
#ifdef VSWTCH
d_tio.c_cc[VSWTCH] = CSWTCH; /* usually '^Z' */
#endif
I checked on debian Linux's kterm but could not found MIN=0 problem. I
also looked into debian kterm source code but could not found any
treatment for MIN=0 problem. I guess there is some differences in
terminal emulation library or terminfo database(?) between FreeBSD and
debian.
TOMITA Yoshinori [EMAIL PROTECTED] wrote:
debianなLinuxのktermでは、min=0になることはないのですが、端末の設定が新
しく開くktermへは引き継がれない、という副作用が発生しています(それは、
たいした問題ではない気もします)。
I investigated the mystery why debian linux's kterm works OK and
FreeBSD's does not.
In main.c, there is a defined(linux) block,
/*
* set up the tty modes
*/
{
#if defined(USE_SYSV_TERMIO) || defined(USE_POSIX_TERMIOS)
#if defined(umips) || defined(CRAY) || defined(linux)
/* If the control