かってきままな日々
2020-02-11 (Tu) [長年日記]
_ 建国記念日
…は月曜に移動しないんだな。
_ またメールが届かない?
今朝目が覚めた時、メールを確認したら何も来てなくて、また?? と思った。
そこで gmail から自分宛にメール送ったら届いた。大丈夫っぽいので、そのまま放置。
1時間後くらいにいくつかメール届いた。
このメールサーバ、まだ不安だなぁ。
_ assignment in conditional expression
https://ja.stackoverflow.com/questions/1961/
kernel の device driver を書く時、I/O ポートを
volatile unsigned char *port;
とか定義して、
*port = 0x12;
とか書くと思うし、
#define PORT (*port)
とか書くこともあると思う。
こういう場合、
if ((PORT = func()) == 0x12)
と
PORT = func();
if (PORT == 0x12)
では意味が異なってくるんだよね。 前者は I/O ポートから読まないけど、後者は読む。 書いたものがそのまま読めるだけのポートなら遅くなるだけで済むけど、 そうでなかったら、全然違う結果になってしまう。
まぁ、そんなことを気にしなきゃいけない人は極少数だから、 「分けるべし!」に異論はないんだけど、 「ほとんどのコーディング規約で許可されない」ほどのものなのか。
私は好んで使ってるなぁ。 返り値を確認しなきゃいけないことはそりゃ頻繁にあるし、 そういう場合は一時的に分けてるんだけど。
話が C じゃなくなるけど、
rubocop の default 設定が私の感性と合わないらしく、
しょっちゅう怒られるんだよね…
_ scp のバグに遭遇
scp で巨大なファイルを手元にコピーしたい。よくある話。
時間がかかるので、nohup 付けて &
も付けて background にした。
その後、端末が落ちてしまった。
そうすると、転送が止まってしまった。scp のプロセスは生きているのに。
という話。
https://blog.ingage.jp/entry/2020/02/10/114509
↑途中まで調べられるだけ調べたので、ブログ記事にした。というのが昨日。
今日は原因を更に追求してみて、解ったので書いてみる。
まずは zsh が SIGHUP を送っているのは確からしい。
で、データの流れを図にすると、↓こんな感じ。
scp -- (PIPE) -- ssh -- (TCP) -- sshd --...
↓
ファイル
scp が fork して ssh プロセスを作り、ssh が sshd に TCP で接続し、 おそらくその向こうにも scp がいて、ファイルをこっち側の scp に送り、 scp がファイルに落とす。という感じ。
で、
- nohup を付けてるので、scp は SIGHUP が SIG_IGN の状態で起動する
- scp が ssh を起動する。この時、SIGHUP は SIG_IGN。
- scp は SIGHUP を自前のハンドラに設定する。
- いろいろやった後、転送が始まる。
- 端末が落ちる。
- zsh が scp と ssh に SIGHUP を送る。
- scp では自前のハンドラが呼ばれる。ssh では無視される。
- scp の自前ハンドラでは子プロセス (=ssh) に SIGHUP を送る。
- ssh はこの SIGHUP も無視する。
- scp は ssh が終わるのをひたすら待つ。ssh が PIPE 経由でデータを送ってるのを無視して。
- ssh は scp がデータを受け取ってくれるのを待つ。
こんな状態で止まってるっぽい。
ssh は、SIGHUP ハンドラを設定する時に、既に SIG_IGN だったら設定しないようになっている。 だから SIG_IGN のまま変わらない。しかし、scp は必ず自前ハンドラに設定し、SIGHUP 時に 子プロセスの終了を待つようになっている。
これは scp のバグだと思うな。SIG_IGN の場合は、ハンドラを設定するのはともかくとして、 子プロセスの終了を待っちゃいかんと思う。SIG_IGN でなくても、ハンドラ内で待つなんて、 行儀が悪い。
バグレポートは… どうしようかと思ったんだけど、 こんな症状、今までに報告がなかったとは思えないんだよね… たぶん、報告はあったけど放置してる、って状態なんじゃないかな、と。
http://bugzilla.mindrot.org/show_bug.cgi?id=2091
↑これやね。最近になってログが添付されたりして、進みそうな気配。 私の調査結果をコメントしとこ。
たぶん、最近の流行としては、disown を使うんだろうな。 そうすれば、shell の job 管理から外れて、signal が飛ばなくなる? いや、tty から飛ぶことはありそうに思うけど。
https://qiita.com/aosho235/items/24bf88462811eccbdec8
↑UART ドライバから飛ぶらしい。じゃぁ ssh の場合は関係ないね。
つまり、serial tty からの login でない限りは、
command < /dev/null >& /dev/null &
disown
で大丈夫ってことかな。