接続されていない状態でパイプが削除されると、名前付きパイプブロックを永久に開きます。

接続されていない状態でパイプが削除されると、名前付きパイプブロックを永久に開きます。

次のシェルコマンドを試してください。

mkfifo /tmp/test.pipe

ls -1 /tmp > /tmp/test.pipe &

rm /tmp/test.pipe
mkfifo /tmp/test.pipe
cat /tmp/test.pipe &

jobs

このlsコマンドは単なる例であり、名前付きパイプに書き込むすべてのプロセスにすることができます。ここで重要なのは、プロセスが書き込み用にパイプを開こうとする試みをブロックすることです。別のプロセスが表示され、パイプを削除します。同じ名前の新しいパイプが作成され、catプロセス(つまり、読み取るために開こうとするすべてのプロセス)は、他のプロセスが同じ名前の新しいパイプに書き込むのを待つのをブロックします。どちらのプロセスもそれぞれのパイプ接続を待っています。これは背景を一覧表示することで確認できますjobs

catパイプから実際に読み取るプロセスは実際にパイプを置き換えたプロセスであるため、ブロック(またはパイプから読みたいプロセス)についてはあまり心配しません。実際、私は読むプロセスに全く興味がありません。唯一のcat例は、両方のプロセスが同じパイプファイル名を参照しますが、明らかに異なるパイプインスタンスを使用するという証拠です。ただし、このデッドロックの例は、逆の場合でもブロックされます。つまり、書き込み用に開かずにパイプを削除すると、読み取りプロセスが永久にブロックされます。

私の焦点は書き込みプロセスをブロックすることです(ls私の例では)。書こうとした元のパイプが同じ名前の新しいパイプに置き換えられたことは決して気付いていません。

プロセスが存在しなくなった名前付きパイプへの書き込みアクセスをブロックする状況をLinuxで識別する方法はありますか?あなたはroot権限を持つことができ、関連するすべてのプロセスのPIDを知っています。特に、書く過程では、これが事実かもしれないし、そうでないかもしれないことを知っているので、もっとそうです。しかし、わかりません(それは私はこのプロセスで実際にこのような問題が発生した場合、終了できます。ファイルシステムに物理的に存在しなくなった名前付きパイプへのアクセスをブロックするプロセスをどのように見つけることができますか?

明らかに、ls /proc/<PID>/fd両方のプロセスのいずれかのパイプにアクセスするためのファイル記述子は、パイプの両端が接続されていない限りリストされません。つまり、ls /proc/<PID>/fd2つのプロセスのパイプのファイルは、システムコールが2つのプロセス記述子の最後に正常に返された後にのみリストされます。 。私の場合は2つが違うので半接続パイプ名は同じですが、プロセスはすべてリストされません。

ベストアンサー1

提案通りジュリー・ペレティエ、私は議論で見つけた解決策にこの答えを与えます。

私の質問で説明されているデッドロックの状況を簡単に識別することはできませんが、先制的に対処することはできます。ベント誰かが削除する前に解決策と呼ばれるパイプです(私の場合のように削除を避けることができない場合)。これらの換気により、現在のパイプを開こうとするとブロックされているすべてのライターが操作を正常に開くことができますが、実際の書き込み操作中に失敗する可能性があります(->破損したパイプ)。閉じ込めよりも失敗する方が良いかもしれません。すぐに次のデッドロックに陥らないようにするには、換気する前にパイプを移動してから取り外す必要があります。

# rename the pipe, i.e. move it out of the way
mv -f /tmp/test.pipe /tmp/test.pipe~ 2>/dev/null

# vent the pipe, i.e. shortly open it for reading but don't read from it.
# call the subshell dd and empty echo calls in the background to avoid 
# deadlocking on redundant venting.
(dd if=/tmp/test.pipe~ count=0 2>/dev/null & echo -n "" >/tmp/test.pipe~ &)

# delete the old pipe
rm -f /tmp/test.pipe~

どのプログラムが間違った削除を行ったかを知っている場合は、そのプログラムを削除を中止して中断する小さなスクリプトでラップできます。

おすすめ記事