segfaultingプログラムからのパイプ出力


13

ttf2afm時々セグメンテーション違反を起こすプログラムと、特にそうではないプログラム(具体的には、tetex 3.0の一部)を呼び出すスクリプトがあります。必要な情報は常にセグメンテーション違反が発生するに出力されますが、プログラムの失敗時にパイプのリダイレクトが失敗し、パイプに何も出力されないようにするのに苦労しています。

FIFOを介してリダイレクトを試行trueし、最後にプロセスをかっこで囲み、シェル関数から実行し、で囲みましたsh -cが、スクリプトはプロセスが何も、リダイレクトまたはその他を出力しないようにしました。

私はそれがコマンドラインから完全に出力できるが、何らかの理由でスクリプトからではないので、出力できることを知っています。

私の質問は、スクリプトがプログラムがセグメンテーション違反を起こし、出力を提供するという事実を無視する方法はありますか?

BASH 4.1.10(2)-releaseを実行しています。

回答:


12

プログラムは通常、効率のために出力をバッファリングします。つまり、メモリ領域(バッファと呼ばれる)に出力を蓄積し、実際にバッファがいっぱいになったとき、またはプログラムの特定のキーポイントでのみ出力を取得します。プログラムが正常に終了すると、出力バッファーがフラッシュされます(つまり、残っているデータが出力されます)。セグメンテーション違反が発生すると、バッファのコンテンツは失われます。

プログラムの出力がターミナルに接続されている場合(通常のファイルまたはパイプとは対照的に)の動作が異なるため、ターミナルでプログラムを直接実行する場合、この効果は見られません。端末では、デフォルトの動作は各行の終わりでバッファをフラッシュすることです。そのため、プログラムがセグメンテーション違反になる時点までに生成されたすべての完全な行が表示されます。

プログラムを強制的に端末で実行し、その出力を収集できます。最も簡単な方法は、実行することscriptです。回避する必要がある厄介な点がいくつかあります。

  • script トランスクリプトファイルにヘッダー行を追加します。後で削除する必要があります。
  • script はコマンドのステータスコードを返しません。そのため、セグメンテーション違反やその他のエラーについて知りたい場合は、どこかに保存する必要があります。
  • script通常の出力とエラー出力が発生します。エラー出力を別のファイルに保存することをお勧めします。
export FONT="foo"
script -q -c '
    ttf2afm "$FONT.ttf" 2>"$FONT.ttf2afm-err";
    echo $? >"$FONT.ttf2afm-status"
' "$FONT.ttf2afm-typescript"
tail -n +2 <"$FONT.ttf2afm-typescript" >"foo.afm"
rm "$FONT.ttf2afm-typescript"
if [ "$(cat "$FONT.ttf2afm-status")" -ne 0 ]; then
  echo 1>&2 "Warning: ttf2afm failed"
  cat "$FONT.ttf2afm-err"
fi

出力バッファーを0などに設定するシェル設定など、よりエレガントなソリューションはありませんか?
amphetamachine

4

私は最終的に試行錯誤の過程でそれを理解しました。解決策は一種複雑です:

(trap 'true' ERR; exec ttf2afm "$FONT") |
grep ...

どうやら、exec原因ttf2afmがトラップされたエラーでサブシェルプロセスを引き継いでいるので、セグメンテーション違反が問題にならない環境で動作しているようです。

オールインクルーシブERR信号をトラップすると、サブシェルが停止し、プログラムが失敗したときにメインスクリプトに信号が送信されます。

唯一の問題は、プロセスがセグメンテーション違反になると、カーネル自体がスタックトレースガベージの全束を直接コンソールデバイスに出力することです。したがって、それが出力されるのを防ぐ方法はありません。 stdoutやstderrには影響しないため。


3
これがうまくいくと嬉しいですが、bashが出力バッファサイズを0に設定しているからではないことを確信できます。bashはttf2afm直接使用されるバッファリングに影響しません。どのよう(trap true ERR; exec ttf2afm "$FONT")| …に振る舞うのかttf2afm "$FONT" | …
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.