これな
症状
nyagos から OpenSSH を起動して、パスワードプロンプトで Ctrl-C を押下すると、nyagos に復帰してこなくなる(ように見える)。
原因
これは実は nyagos には復帰しているのだが、コンソールのモードがパスワード表示向けの状態から元に戻っていないだけである。なので、画面が更新されないが「exit」と入力すると普通に終了する。
対応
コマンドを実行した後、コンソールの出力のモードをいちいち元に戻すようにした。入力のモードについては既に対応していたので、同じような対応を出力にもするようにした。
詳しくは差分みて
余談1
このコンソールのモードを変える関数(dos.ChangeConsoleMode)の仕様は我ながらなかなかうまいこと作れていると思う
if restore,err := dos.ChangeConsoleMode(windows.Stdout, dos.ModeSet(enableVirtualTerminalProcessing)) ; err == nil { defer restore() }
- モードを元に戻す関数(クロージャ)を戻り値に変えす。一時的にモードを変えるだけなら、これを defer で戻すようにすればよい
- モードのセット・リセットは、
dos.ModeOp
というインターフェイスを実装したdos.ModeSet
,dos.ModeReset
という型をパラメータとして0個以上渡せばよい。 - コンソールのハンドルはいちいち自分で
"$CONIN"
"$CONOUT"
をオープンしなければいけないと思いがちだが、実は準標準のgolang.org/x/sys/windows
に windows.Stdout とか windows.Stdin がそのままあるので、これを使った方が早い。
余談2
なぜ、Ctrl-C で OpenSSH を中断すると、コンソールのモードを元に戻してくれないのか? beepcap さんによると、CMD.EXE や PowerShell 上では同症状は発生しなかったそうだ。
可能性としては以下の2説がある。
- CMD.EXE や PowerShell はコマンド実行ごとにいちいちコンソールモードをリセットしている
- Ctrl-C をキャッチした時の子プロセスの殺し方がまずい(SIGKILL相当)ので、OpenSSH が SIGINT 扱いでハンドルできない
nyagos の Ctrl-C の扱いについては、最近(go-tty導入前後)になってからうまく処理できなくなったので、 "os/exec".Run
を参考にして最近実装しなおしたのだが…見直しが必要かもしれない。
Ctrl-C の取扱については、現在のように Go言語の "os/signal" の関数を使うほか、Windows のそれ用の API SetConsoleCtrlHandlerがある。 おいおいと調べなくては…