StackOverflowには素晴らしい答えがあります。デーモンに対してより良いロックを提供(で合成エドゥアルド・フリリ)はデーモンプロセスに依存しない汎用PIDファイルロック機構です。 PIDロックファイルが時々問題を引き起こす理由についての良い意見がたくさんあるので、ここでは繰り返しません。
つまり、ソリューションは、デーモンがSIGKILLされた後も持続するファイルに依存するのではなく、名前でソケットを追跡するLinux抽象名前空間ドメインソケットに依存します。この例では、プロセスが終了するとLinuxがソケットを解放するように見えます。
しかし、バインディングプロセスがSIGKILLとマークされている場合、Linuxが抽象ソケットを使用して正確に何をしているかを説明する明確な文書はLinuxにありません。知っている人はいますか?
つまり、抽象ソケットが再利用するために正確にいつリリースされるのですか?
問題が完全に解決されない限り、PIDファイルメカニズムを抽象ソケットに置き換えたくありません。
答え1
私はこの質問を1年前に投稿しましたが、明確な文書が不足して不満がありました。アップデートがあるかどうか、Linuxドキュメントをもう一度確認する必要があると思いましたが、今行ってもいいです。これを見て:
抽象ソケット
ソケット権限は抽象ソケットに対して意味がありません。プロセスumask(2)は抽象ソケットをバインドすることに影響を与えず、オブジェクトの所有権と権限の変更(fchown(2)とfchmod(2)を介して)は抽象ソケットには影響しません。効果。ソケットのアクセシビリティ。
ソケットへのすべてのオープン参照が閉じられると、抽象ソケットは自動的に消えます。
返品、Linuxプログラミングインターフェース渡すマイケルクリーク扱う問題(クロスポスト)この他の答え):
57.6 Linux抽象ソケット名前空間
いわゆる抽象名前空間は、ファイルシステムに名前を生成せずにUNIXドメインソケットを名前にバインドできるLinux固有の機能です。これはいくつかの潜在的な利点を提供します。
- ファイルシステム内の既存の名前との競合の可能性について心配する必要はありません。
- 使用が終わったら、ソケットパス名を切断する必要はありません。ソケットが閉じると、抽象名は自動的に削除されます。
- ソケットのファイルシステムパス名を作成する必要はありません。これは、chroot環境またはファイルシステムへの書き込み権限がない場合に便利です。
抽象バインディングを生成するには、最初のバイトを指定します。 ソーラーパスフィールドはNULLバイト(\ 0)です。 [...]
@ user3188445の答えと一緒に、これは質問を非常に正確に説明すると思います。
つまり、SIGKILLプロセスが開いているすべてのソケットを閉じるという仮定がまだ存在します。これは合理的な仮定のように見えますが、この動作を定義する文書はありません。
答え2
はい、Linuxは適切なポイントまで抽象ソケットを自動的に「クリーンアップ」します。以下は、これを確認するために使用できる最小限の実際の例です。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
int
main(int argc, char **argv)
{
int s;
struct sockaddr_un sun;
if (argc != 2 || strlen(argv[1]) + 1 > sizeof(sun.sun_path)) {
fprintf(stderr, "usage: %s abstract-path\n", argv[0]);
exit(1);
}
s = socket(AF_UNIX, SOCK_STREAM, 0);
if (s < 0) {
perror("socket");
exit(1);
}
memset(&sun, 0, sizeof(sun));
sun.sun_family = AF_UNIX;
strcpy(sun.sun_path + 1, argv[1]);
if (bind(s, (struct sockaddr *) &sun, sizeof(sun))) {
perror("bind");
exit(1);
}
pause();
}
プログラムを実行する./a.out /test-socket &
とss -ax | grep test-socket
、使用しているソケットを表示できます。その後kill %./a.out
、およびはss -ax
ソケットが消えたことを示します。
しかし、どの文書でもこのクリーンアップを見つけることができない理由は、実際には非抽象Unixドメインソケットをクリーンアップする方法のクリーンアップではないからです。非抽象ソケットは実際にinodeを割り当て、ディレクトリにエントリを作成します。このエントリはデフォルトのファイルシステムでクリーンアップする必要があります。対照的に、抽象ソケットはTCPまたはUDPポート番号に似ています。もちろん、TCPポートをバインドして終了すると、TCPポートは再び解放されます。ただし、何を使用しても、16ビット数はまだ抽象的に存在し、常に存在します。ポート番号の名前空間は1-65535で、変更やクリーンアップは必要ありません。
したがって、抽象ソケット名をTCPまたはUDPポート番号と考えることができます。これは、パス名のように見えますが、そうでない可能性の高いポート番号のセットから選択されました。同じポート番号を2回バインドできません(禁止SO_REUSEADDR
またはSO_REUSEPORT
)。ただし、ソケットを閉じると(明示的または終了によって暗黙的に)、何もクリーンアップせずにポートが解放されます。