Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

popen システムコール とSIGHUP シグナル

274 views
Skip to first unread message

ma

unread,
Dec 3, 2001, 9:25:10 PM12/3/01
to
あるプログラムにおいて
親プロセスにおいてSIGHUPの
ハンドラを定義しておきます
そのプロセスからforkして
その中でpopenを呼ぶと
SIGHUPシグナルを受取ってしまいます。
プロセスを立ち上げる際、
コンソールより立ち上げ、コンソールをクローズ
したときのみ
SIGHUPシグナルが発生し
通常のターミナルから立ち上げるときは
発生しません。

コンソールでの環境と通常のターミナルの環境
でPOPENやSIGNALについての影響に
何か違いがあるのか ご存知の方教えて下さい

宜しくお願いします。


--

HASHIMOTO, Tsuyoshi

unread,
Dec 4, 2001, 6:08:32 AM12/4/01
to
In article <kvWO7.316$ob6....@news1.dion.ne.jp> "ma" <m...@www.com>
writes:

>コンソールより立ち上げ、コンソールをクローズ
>したときのみ
>SIGHUPシグナルが発生し
>通常のターミナルから立ち上げるときは
>発生しません。

"Unix" の種類 (OS 名) や,版数,そして program/process たちの動作
timing についての情報が不足していますが,例えば,いわゆる SysV 系の
仕様の中に,「端末の制御 process (ある端末を open している process
がいなかった時に open() をかけた process)が消滅する時(その process
を leader とする "session"/"pgrp" に対して)SIGHUP を送る」という項目
があり,この条件に該当している可能性が(もし,その OS が SysV 系統なら)
あります.

その他,端末操作に関連して kernel が送ってくる signal については,
signal 関連のマニュアルか,端末関連のマニュアルに出ている可能性が
高いと思います.

なお,複数 processes の間の動作 timing については strace, truss,
ktrace など(その OS に標準添付されている/移植されている trace tool)
を使って調べる事ができますし,process が open しているファイル(端末等
の特殊ファイル含む)は,lsof という free software を使って調べる事が
可能です.

#なお,popen(3S) は普通「システムコール」ではなく厳密にはそう呼ばない
#はずです.(複数の system callsを使って実装される library 関数のはず)
--
橋本 剛 (HASHIMOTO, Tsuyoshi)

ma

unread,
Dec 4, 2001, 7:59:15 PM12/4/01
to
ご回答ありがとうございます
かなり説明が足りないですね(^^;

OS SunOS 5.6(solaris2.6)

test 環境 signal 発生ケース


  SUN
サーバ  COM ------ COM PC


  pc上でCOMをオープンし 該当プログラムを バックグラウンドで起動
  COMオープンしたターミナルを立ち上げたままにしておけば SIGNALは発生しな

  *
但し、COMオープンしたターミナル(windows上teraterm)をクローズすると 
SIGNALが発生する


  SUN
 サーバ  

  SUNサーバ上にネットワークログイン 仮想ターミナル上で 該当プログラムを
起動
  立上げに使用した際のターミナルはクローズしてもSIGNALは発生しない


該当プログラムは ソケットを用いたサーバクライアント型の処理です

プログラム概要


メイン

sigset (SIGHUP, ハンドラ関数); (ちなみにハンドラ内ではプログラムをexitす
るような仕様になっています)

socket
bind
listen
accept <----------- connect (クライアント)


sigignore(SIGCHLD);

fork

(子)

receive


ディスク容量チェック処理
       popen("df -k","r"); ------->このライブラリ関数がコール
された
                         時点でなぜかSIGHUPが発生す
るらしい

pclose

このデーモンは通常手動でネットワーク経由で上げていたので事象が発生していな
かったのですが
たまたまCOM経由で上げてCOMのターミナルをクローズした場合に サーバプロセス内

子プロセス内の popen 処理で SIGHUPがあがってしまっているようです。

端末の制御 process
(ある端末を open している process
がいなかった時に open() をかけた process)
が消滅する時
(その process を leader とする "session"/"pgrp" に対して)
SIGHUP を送る

上の表現はたいへんわかりずらいのですが
この場合 popen 内で コマンド実行用のsh が起動され 標準入出力が使用されま
すが
そのshが終了した時点でSIGHUPを上げているようなイメージでしょうか?


また 上記ハンドラ内で なぜかsigsetを使用しているのですが
sigactionなる関数に置き換えてテストもしてみたいと思います。


何かございましたら また よろしくお願いいたします。


"HASHIMOTO, Tsuyoshi" <t...@spp.hpc.fujitsu.co.jp> wrote in message
news:snmitbn...@indra.spp.hpc.fujitsu.co.jp...

HASHIMOTO, Tsuyoshi

unread,
Dec 5, 2001, 10:12:41 PM12/5/01
to
#本題とは別に,複数 newsgroups への同時投稿の方法について,気を
#つけて頂きたい事があるので,その点を先に説明します.

In article <XkeP7.440$ob6....@news1.dion.ne.jp> "ma" <m...@www.com>
writes:

>Newsgroups: fj.unix

複数 Newsgroups に記事をポストする必要がある場合上のように「1つだけ
newsgroup を指定した記事を複数回ポストする(この方法はマルチポストと
呼ばれます)」のではなく,「複数の newsgroups を指定した記事を,1回
だけポストする(この方法はクロスポストと呼ばれます)」事を原則にして
下さい.クロスポストは,例えば次のように Newsgroups: 行に複数 groups
を 「,」で区切って書く事で実現できます.

Newsgroups: fj.unix,fj.questions.unix,fj.comp.lang.c

これは,NetNews の使い方についての一種のエチケットと見なされています.
理由としては,次のような事が挙げられます.

(1) 「同一の記事が複数 groups に現れている」事が,記事を読む側にきちん
と情報として伝わる.(これが,本質的です).

- このため(よく出来た News reader (program) を使っている場合)読む
人の都合に合わせて「別の newsgroup で一度読んだ記事は再表示しない」
などの指定ができる.(よって,読む人にとって,時間の節約になります).
- 複数の Newsgroups で別々に議論が進む事による「無駄」が避けられる.
(Followup 記事を書く人により,他の newsgroup での followup 記事が
ある事がそもそも分からないと,他の記事を参考する事ができない他,
(既に別の人が書いているので書く必要がない)同じ内容を書いてしまう
かも知れない).

(2) (主に News server にとって)Network 帯域や disk space を節約できる.

- NetNews の記事は,多くの場合,世界中のサーバに転送されていきます.
「チリも積もれば ...」で(多くの人が)上のエチケットを守った場合と
守らない場合では,(記事の1つ1つは大した大きさではなくても),
最終的には,差が出ます.

なお,(マルチポストはもちろんの事)クロスポストも濫用はつつしむ必要が
あります.また,クロスポストを使う場合は,できるだけ「Followup 記事の
投稿先(希望)Newsgroup」を(できれば1つ)指定しておく事が望ましいと
思います.なお,この時,記事のヘッダに Followup-To: という行を含めて,
そこに Followup 記事の投稿希望先 group 名を書いておくと,よく出来た
news reader を使っている場合,投稿先 group が,その group に自動設定
されるので, Followup 記事を書く側の人にとって,便利な場合が多いかと
思います.(例えば,次のような感じにヘッダ行を書くという話です.なお,
本当のヘッダ行の先頭には tab や space は(もちろん)ありません).

Newsgroups: fj.unix,fj.questions.unix,fj.comp.lang.c
Followup-To: fj.unix

さて,本題の続きも(少しだけですが ^^;)書きます.

>OS SunOS 5.6(solaris2.6)
>test 環境 signal 発生ケース
>  SUN
> サーバ  COM ------ COM PC
>  pc上でCOMをオープンし 該当プログラムを バックグラウンドで起動

...
> 但し、COMオープンしたターミナル(windows上teraterm)をクローズすると 
>SIGNALが発生する

これは,man termio すると出てくる,下記の説明に該当します.

Ioctl Requests termio(7I)
...

Modem Disconnect
When a modem disconnect is detected, a SIGHUP signal is sent
to the terminal's controlling process. Unless other arrange-
ments have been made, these signals cause the process to
terminate. If SIGHUP is ignored or caught, any subsequent
read returns with an end-of-file indication until the termi-
nal is closed.

"Modem" という言葉が使われていますが,これは単に「COM port の先」と
いう意味にとって構いません.

ma

unread,
Dec 6, 2001, 12:02:10 AM12/6/01
to
ご回答ありがとうございます。

NEWS関連のご忠告ありがとうございます。

下記 termio ですが


> If SIGHUP is ignored or caught, any subsequent
> read returns with an end-of-file indication until the termi-
> nal is closed.

この部分が私の能力ではよくわかりません。
噛み砕くとどういうことを言っているのでしょうか?

確かにコンソールのクローズのSIGNALに関係ありそうですが
該当プロセスはバッググラウンドで動作していています。
バッググラウンドでもコンソールのSIGNALを受けてしまうのでしょうか?
仮に そのSIGNALだとしても デーモンが死ぬまでに
タイムラグがあり、popen ライブラリが呼ばれるまでは
デーモンは生きているように思われます。

また 端末の属性を、コンソールではデフォルトが sun になっており
stty -a としましたところ hupcl になっておりましたので
-hupcl にしてから デーモンの立上げを行ってみましたが
状況はあまりかわりませんでした。
(仮想ターミナルでは vt100 で -hupcl がデフォルトでした)

何かヒントになることがございましたら
よろしくお願い致します。


"HASHIMOTO, Tsuyoshi" <t...@spp.hpc.fujitsu.co.jp> wrote in message

news:snmg06p...@indra.spp.hpc.fujitsu.co.jp...

Shigehiko SASAKI

unread,
Dec 6, 2001, 12:54:01 AM12/6/01
to
佐々木@でかいの です。

> 下記 termio ですが
> > If SIGHUP is ignored or caught, any subsequent
> > read returns with an end-of-file indication until the termi-
> > nal is closed.
>
> この部分が私の能力ではよくわかりません。
> 噛み砕くとどういうことを言っているのでしょうか?

% program &
上のようにバックグランドで起動した programは一般にデーモンでは
ありません。単にバックグランドで動いているだけです。
ですから制御端末が落ちれば所属するプロセスグループすべてに
SIGHUPが発行されます。
バックグランドで動いている programはシェルがNOHUPジョブとして
設定してくれているので、SIGHUPを無視しますが、programの子プロセスの
popen()で呼び出した dfはSIGHUPを受け付けてしまいます。

この問題の簡単な解決方法は 制御端末を切り離すなどの処理をして
正しくデーモンとして programを作ることでしょう。
LinuxやFreeBSDだとdaemon()と言う自プロセスをデーモン化する
便利な関数があるのですが、Solarisにはないようですね。

簡単にdaemon()のクローンを書いてみました。
mainの最初のほうで 以下のdaemon() 関数を呼べば正しいデーモンに
なると思います。
数分で書いたコードなので間違いがあるかもしれません。
SunOS5.7で動作確認しました。


でかいの企画 佐々木茂彦
ssa...@dekaino.net

#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>

void daemon(void) {
int fd;

switch (fork()) {

case -1:
perror("fork()");
exit(1);

case 0:
break;

default:
exit(0);
}

if (setsid() == -1) {
perror("setsid()");
exit(1);
}

chdir("/");
fd = open("/dev/null", O_RDWR);
if (fd != -1) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
}
}

ma

unread,
Dec 6, 2001, 1:11:31 AM12/6/01
to
ご回答ありがとうございます。

デーモンについてもう少し詳しく勉強してみます。
わかりやすいご説明ありがとうございました。
また何かございましたら宜しくお願い致します。


"Shigehiko SASAKI" <ssa...@dekaino.net> wrote in message
news:rmk7w0z...@emma.dekaino.net...

Iwao Watanabe

unread,
Dec 6, 2001, 1:02:19 AM12/6/01
to
端末ドライバーのHUPシグナルの設定の差異による現象のようですね。

"ma" <m...@www.com> wrote
in message news:WZCP7.493$ob6....@news1.dion.ne.jp...

>
> また 端末の属性を、コンソールではデフォルトが sun になっており
> stty -a としましたところ hupcl になっておりましたので
> -hupcl にしてから デーモンの立上げを行ってみましたが
> 状況はあまりかわりませんでした。
> (仮想ターミナルでは vt100 で -hupcl がデフォルトでした)

該当箇所を

poepn("stty -hupcl;df -k","r")

... とすればどうですか?

あるいは foo を動かすときに

$ (stty -hupcl;foo )&

とするとか。

$ nohup foo &

としてみるという手も在ります。
foo がバックグラウンドで動作するなら
特に問題にはならないと思います。

ma

unread,
Dec 6, 2001, 2:07:11 AM12/6/01
to
またひとつ確認がございます。

下記 ご説明でいままでの現象がきれいに説明できると
思うのですが、通常のネットワーク経由でログインした
ターミナルから上げた場合は 該当プログラムが
デーモンとして 作られていなくても
落ちないのはなぜでしょうか?
popen の子プロセスまで -nohup の環境が引き継がれるということでしょうか?

よろしくお願い致します。

"Shigehiko SASAKI" <ssa...@dekaino.net> wrote in message
news:rmk7w0z...@emma.dekaino.net...

ma

unread,
Dec 6, 2001, 7:17:39 AM12/6/01
to
ご回答ありがとうございます。

"Iwao Watanabe" <iw...@DSL.gr.jp> wrote in message
news:9un1lc$kpp$1...@sv.dsl.gr.jp...


> 端末ドライバーのHUPシグナルの設定の差異による現象のようですね。
>
> "ma" <m...@www.com> wrote
> in message news:WZCP7.493$ob6....@news1.dion.ne.jp...
>
> >
> > また 端末の属性を、コンソールではデフォルトが sun になっており
> > stty -a としましたところ hupcl になっておりましたので
> > -hupcl にしてから デーモンの立上げを行ってみましたが
> > 状況はあまりかわりませんでした。
> > (仮想ターミナルでは vt100 で -hupcl がデフォルトでした)
>
> 該当箇所を
>
> poepn("stty -hupcl;df -k","r")
>
> ... とすればどうですか?

特に動作上は変わり映えしないようでした。
こちらでももう少し勉強してみます。
なにかございましたら 宜しくお願い致します。

HASHIMOTO, Tsuyoshi

unread,
Dec 6, 2001, 7:18:32 AM12/6/01
to
#再び NetNews の使い方についてうるさい事を言ってしまいますが ^^;
#「follow up 記事(の末尾)に,元記事全文をつけたままにする」事は,
#NetNews では,あまり良くない事と見なされています.「説明の都合上
#必要な部分のみの引用」の方が好まれます.(「そもそも文書に対する
#引用とは本来そうあるべき」という考えが基本で,もう一つは,やはり
#Network 帯域,disk space についての意識から来ているとおもいます).

In article <_OEP7.497$ob6....@news1.dion.ne.jp> "ma" <m...@www.com>
writes:

>思うのですが、通常のネットワーク経由でログインした
>ターミナルから上げた場合は 該当プログラムが

「通常のネットワーク」は COM port と違って,Modem と見なされないために
<snmg06p...@indra.spp.hpc.fujitsu.co.jp> で引用したマニュアルの記述
は当てはまらず,SIGHUP が送られない ... という事ではないでしょうか?

#実際に何がおきているかは,例えば truss というコマンドを使って,
# truss -aelf -vall command arg1 arg2 ... & などとしてみれば,分かる
#かと思います.truss の各 option の意味はマニュアルを見て下さい.なお,
#truss で既に起動済みの (backgrond) process をトレースする事も -p を
#指定すれば出来ます.truss は,こうした問題の調査に非常に役立ちます.

ちなみに,現象発生は「SIGHUP が送られるか送られないか」により決まって
いますが,「SIGHUP が送られた後で,その「端末ファイル」をアクセスする
時に何が起こるか?」というのは,また別の話です.以下の部分はその点に
ついてです.

>> > > If SIGHUP is ignored or caught, any subsequent
>> > > read returns with an end-of-file indication until the termi-
>> > > nal is closed.
>> > この部分が私の能力ではよくわかりません。
>> > 噛み砕くとどういうことを言っているのでしょうか?

「この部分」が(文字通り)上の3行を指すなら,ここに書いてある内容は,
(SIGHUP が無視 (ignored) または handler が設定されている (caught) 場合
には process が消滅しないので,「端末ファイル」に対するアクセス,特に
read アクセスを続ける場合がありえますから,その場合)「read に対しては
必ず EOF が返る」そして「その状態は,その「端末ファイル」を close する
まで変わらない (until ... closed) 」という事を言っています.ところで,

>> LinuxやFreeBSDだとdaemon()と言う自プロセスをデーモン化する
>> 便利な関数があるのですが、Solarisにはないようですね。

この通りですが,最近 SUN は Linux の API を(free software 移植性を
上げるため)Solaris に採り入れようとしているようなので,ひょっとして,
Solaris 9 (あるいは,その後の版で)追加される可能性はあるかも???

マニュアルに書かれていないので,いつまで残る機能かは分かりませんが,
/usr/bin/setpgrp というコマンドは,「制御端末を切り離す」処理をして,
指定されたコマンドを(引数もつけて)実行するようです.i.e. 使い方は,

/usr/bin/setpgrp command arg1 arg2 ... &

という形なのでしょう(マニュアルもない非公開機能で,「無保証」ですし,
truss で見ると,setsid() ではなく(「廃止予定」の)setpgrp() を使う点
からして,「見るからに古そう」なコマンドですから,お勧めはできません.^^;
似たようなコマンドを自分で作って使う事は比較的容易なので,その方が堅実
と思います).

# 2.5 ないしそれ以前の古い版の Solaris の rc script のどれかで,上記
#コマンドが使われていたような気がします.2.6 では rc script は使って
#いないと思いますが,setpgrp コマンドは,まだ残っているようです.

ma

unread,
Dec 6, 2001, 8:04:01 PM12/6/01
to
ご回答ありがとうございます。

プログラム自体をデーモン化するのが
一番きれいなのでしょうが
時間がありませんものですから
下記コマンドで 試してみましたところ
シグナルを受け取らなくなりました。

とりあえずは 表面上
思うように動作するようになっているように見られます。

質問ですが
下記コマンドを使用する上で 注意点など ご存知でしょうか?

よろしくお願い致します。

HASHIMOTO, Tsuyoshi

unread,
Dec 7, 2001, 3:10:47 AM12/7/01
to
In article <zAUP7.571$ob6....@news1.dion.ne.jp> "ma" <m...@www.com>
writes:

>下記コマンドを使用する上で 注意点など ご存知でしょうか?

「既に <snmelm8...@indra.spp.hpc.fujitsu.co.jp> で書いた事が全て」
です.(マニュアルすらなく,非公開/無保証で,将来の OS 改版に際しては
なくなるかも知れません.中で何をしているかは,truss の結果を見て比較的
容易に推測がつくはずと思います.もし推測ができないようなら「無保証かつ
ソースを見ることのできないコマンド」を「自分自身でリスクを負って使う」
という立場に身をおくのは気が重いと思いますから,より正統的な「daemon
を daemon らしくする」ないし,せめて同様のコマンドを自作しての解決策に
移行する事を考えるのが「堅実」な考え方と思います).

/usr/bin/setpgrp 同様のコマンドは setsid() + fork() + execvp() を順に
呼び出せば実装可能のはずです.なお,daemon になる処理の sample コード
として,Stevens の「UNIX ネットワークプログラミング」という本の sample
コード (stevens.netprog.tar.Z という名前で,あちこちのサイトにある tar
archive の中に daemon.c という名で入っています) も (古い System V の
system call setpgrp() は setsid() で置き換える方が良い点を除き) 使える
と思いますし,Rago の「詳解 UNIX ネットワークプログラミング」という本
の sample (こちらは rago.netprog.tar.Z) の ex2.4.16.c は,Solaris 2.x,
7, 8 では,そのまま使えるはずです.これらは,stevens.advprog.tar.Z と
共に,いろいろな system call や library 関数の使用例を調べるのに役立つ
と思いますから,今回使うかどうかは別として,get しておくとよいかも?

ところで,また NetNews の話ですが,「クロスポスト」については,かなり
「特別な状況で慎重に使うもの」と考えられていますので,単に「自分の質問
に確実に気がついて欲しい」という理由では使わないで下さい.議論が続いて
いる途中で話の内容が変わってきて group を移動する途中に使うなど,複数
の group に現れる事の「客観的な利益」が後述の「group を絞る利益」より
大きい」と信じる「客観的な理由」がある場合に限って使うべきと思います.

#例えば,http://www.tcn.ne.jp/~kisimoto/aruki/qa-a03.txt なども参照.

NetNews の記事は,後から「公共の記録」として参照されるものでもあるので,
その場合できるだけ少ない(できれば1つだけの十分適切な) group にだけ
現れる方が記録として価値が高まります.この価値を減らす代償は「投稿の際
に記事を見る/議論に参加する人の多くにとっての利益」以外では不十分です.

今回の話題だと,fj.questions.unix と fj.unix で最初迷うのは一応分かり
ますが実は一方で十分ですし,fj.comp.lang.c は「OS 依存性が強い」と指摘
が出る話題と分かった時点で,外してよい/外すべきだったと思います.
#実は,この記事自体のクロスポスト先も,ずいぶん迷って決めました,

0 new messages