2016-12-08 19 views
2

Iveは "中断されたシステムコール"というメッセージを受け取り、正直な理由を本当に知りません。私の宿題は、クライアントスクリプトと通信するためにFIFOを使用するサーバスクリプトを書くことです。基本的には動作しますが、このメッセージを取り除く方法はわかりません。提案をいただければ幸いです。 bash中断されたシステムコール

私のサーバースクリプト:インタプリタ豊かなこの行がするとき

#!/bin/bash 

server=serwerfifo 

if [[ "$1" ]]; then 
    if [[ ! -p $1 ]]; then 
     echo "Reader(klient) not running" 
    else 
     echo $(expr $2 + $2) > $1 & 
    fi 
else 
    trap "" SIGHUP SIGTERM SIGCHLD 
    trap "exit 0" SIGUSR1 

    if [[ ! -p $server ]]; then 
     mkfifo $server 
    fi 

    while true 
    do 
     if read line < $server; then 
      $0 $line & 
     fi 
    done 
fi 

メッセージが表示されます(。以前のコメントを置き換え)

if read line < $server; then 
+0

http://shellcheck.net/はあなたの友人です(EINTRの問題ではありませんが、一般的にはここにはたくさんのバグがあります)。 –

+0

ところで、個々の読書用にあなたのFIFOをもう一度開くことは意図的なのですか?それは一般的には良いことではありません。 –

+0

私の意図は明らかではありませんが、これは同時実行プログラミングの私の前のステップです:) – dimon

答えて

0

まず、

$0 $line & 

べきbe

"$0" "$server" "$line" & 

プロデューサコードではFIFOの名前が$1であると想定されているためです。二重引用符は、$0$server、または$lineのいずれかにスペースやその他の特別な(bashへの)文字が含まれている場合です。

cygwinでは、片方の端末でfoo.shを手動で実行し、別の端末でfoo.sh serwerfifo 4を手動で実行してコードをテストすることができました。しかし、私は "中断されたシステムコール"を再現できませんでした。しかし、私は、foo.sh端末で倍増値の無限ループを得ました。その意図でしたか?あなたが作っている - その理由は...消費者側は、出力の別のラインを生産、再び$0 ... &を呼び出すところ$0 ... &のすべての呼び出しは、消費するreadのための出力の別のラインを生成することEINTRに関して

1

ですFIFOを繰り返し再オープンすることにより、不必要に競合状態になりやすいコード。あなたがしなければならないより頻繁にそれをしないでください - 作家が閉じて(そしてあなたがEOFを取得するまで)単一のハンドルを使用してください。

while :; do # if we hit end-of-FIFO, then loop around and try to reopen 
    while read -r line; do 
    "$0" "$line" & 
    done < "$server" 
done 

< "$server"ことはないreadのループに、ですので、あなたの作家によって書かれた複数の行を持っている場合、それはFIFOが閉じる前に、それらの複数のラインをリーダーで読み取ることになります。


ここで他の関連する事柄は、非同期イベントを非同期にするバックグラウンドプロセスの使用です。 実際には完全に合法的に中断されたシステムコールを得ることができます。特に、予期しない時間にオープンとクローズの操作が発生したときは:が許可されています userlandに、別の試みは成功する)。これはエラーではなく、正当で許容される結果です。

+0

これは私たちが今対処していることであり、この状況を避けなければならない点ですバックグラウンドで複数のプロセスで作業する場合 – dimon

+0

決定的な振る舞いが必要な場合は、それがロックの目的です。あなたが探していたものに '群れ 'を使う方法を示す答えを考えてみませんか? –

+0

@dimon、...もう一つは、POSIXのセマンティクスごとに、カーネルは*する必要があるときはいつでもEINTR *を返すことができます。理論的には、それは非同期/並行性がなくても起こる可能性があります。したがって、現時点で*現時点で*発生することが観察される状況下でのみ起こると仮定してコードを記述すると、壊れやすいコード。 APIが約束しているもの、つまりEINTRが本当に本当にいつでも起こりうると仮定するだけで、異なる状況(一時停止/再開サイクル、一時的な障害、&c)で発生したときに驚くことはありません。 –

関連する問題