ToDo:
Execve[]へのフロントエンドとして Execvpe[]と Execvp[]を実装しました。
Execvp[file_, {argv___}, options___]は、 execvp(3)相当でファイル名と引数列を渡すと 必要ならPATH変数で指定された検索パスから外部コマンドを 探し出し、現状の環境変数を引き継いで Execve[]します。
Execvpe[file_, {argv___}, {env___}, options___]は、 Execvp[]に環境envを渡せるようにしたものです。
なんで、execvpe(3)が無いんだろう... (execve(2)は、PATHの自動検索は行わないのがポイント)
前々から、やろうとしていた BidirectionalPipe[]の High Level定義への 置き換えを実施しました。 これで、Fortranと Cの間の文字列受け渡し(null終端忘れてるとか...) などの問題や、execlp(3)を使っているのに、コマンド名以外の引数を 渡せない問題が解消されます。
新しいプロトタイプは、以下の通り。
BidirectionalPipe[file_String, {argv___String}, Options___]
オプションとしては、Execve[]へのオプション(ForceCloseOnExec, CloseStd) や、子プロセスのIDを受け取るための PID:>varオプション、 環境を渡すための Environments->{env___String}オプションが使えます。 デフォルトでは、呼び出し時点の環境全体が子プロセスへ渡されます。
OpenRead["!ls -l /usr/include"]相当のことを BidirectionalPipe[]で書くと
{in, out} = BidirectionalPipe["/bin/ls", {"ls", "-l", "/usr/include"}, PID:>pid]; l = Table[If[s = Read[in, String]; s === EndOfFile, Break[], s], {Infinity}]; Close[in]; Close[out]; Wait4[pid];
と、なります。 注意すべきは、閉じるべきファイル記述子が送信/受信用の二つあること、 子プロセスの最後を看取ってやる必要があることです。 通信終了後に子プロセスが自発的に死なない場合やエラー等で 強制切断するときは、Kill[]でシグナルを送って親プロセスから 明示的に殺す必要があります。 (パイプを閉じれば、子プロセス側では 読み込みに対しては EOF、 書き込みに対しては SIGPIPEが発生するので、例外処理が正しく 実装されている場合は read/write発行時には死んでくれる筈ですが、 内部で無限ループしたりすると親プロセスが死ぬまで残留することに なるので、停止が期待できない場合にはやはり明示的に殺す必要があります。) また、Kill[]で明示的に殺した場合も Wait[]かWait4[]で 最後を看取らないとプロセステーブル上のリソースは開放されないので unix初心者は要注意。
カテゴリー: Admin | Emacs | EPICS | Fortran | FreeBSD | GCC | hgsubversion | IPv6 | KEKB | LHC | Lisp | LLVM | MADX | Ryzen | SAD | samba | tDiary | unix | WWW | YaSAI | お仕事 | イベント | 出張 | 宴会 | 数学 | 艦これ | 買いもの | 追記 | 雑記