1

C++ では、一時ディレクトリに書き込む必要のある関数がいくつかあります。理想的には、(I/O オーバーヘッドを最小限に抑えるため) すべてが書き込まれる 1 つの一時ディレクトリのみが作成されます。プログラムが終了すると、そのディレクトリは自動的に削除されます。

ただし、実際にディレクトリを使用する関数のみがその作成と削除を担当する必要があると思うため、メイン関数で一時ディレクトリの作成と削除を処理したくありません。また、メイン関数は、一時ディレクトリが使用されていることを必ずしも認識していません。

これが私が試したことです(以下のコードを参照):どこからでもグローバルに呼び出すことができるgetTempDir()関数は、最初の呼び出しでのみディレクトリを作成し、すべての呼び出しでディレクトリ名を返します。最初の呼び出しでは、デストラクタがディレクトリを削除する小さな DirRemover オブジェクトへの静的な boost::shared_ptr も作成します。そのデストラクタは、プログラムの終了時に自動的に呼び出されます。

問題は、プログラムの終了に失敗した場合や kill などで FileRemover デストラクタを呼び出さないことです。より良い解決策はありますか?

コードは次のとおりです。

std::string getTempDir(){
  static bool alreadyThere = false;
  static std::string name = "";
  if(!alreadyThere){
    // create dir with
    // popen("mktemp -p /tmp","r")) 
    // and store its name in 'name' 
    removeAtEnd(name);
    alreadyThere = true;
  }
  return name;
}

void removeAtEnd(const std::string& name){
  static boost::shared_ptr<DirRemover> remover(new DirRemover(name));
}

struct DirRemover {
  std::string name;
  DirRemover(const std::string& n) : name(n){}
  ~DirRemover(){
    // remove 'name' dir with popen("rm -r ...")
  }
};
4

4 に答える 4

2

Unix の場合:

::signal(SIGINT, sigintHandler);
::signal(SIGKILL, sigkillHandler); //etc

これらのハンドラーが終了イベントをイベントキュー (または同等のもの) にプッシュし、シグナルを無視するようにします。その後、アプリは正常に終了できます。ただし、無視できないシグナル (SIGKILL) が 1 つあります。それを処理するには、キル時に本当に解放したい最も重要なリソースを決定し(一時ディレクトリがそれほど重要であるとは確信していません。次の起動時に削除するだけです)、ハンドラーで、関連するシングルトンの関数を呼び出します.release

シングルトンについて詳しく説明します。::signalバインドされた関数を呼び出すことができないため、ハンドラーはシングルトン/グローバルにのみアクセスできます。あなたのデザインがシングルトンで物事を整理していない場合 (そうすべきではありません)、それでも多くの場合、それをハックすることができます。たとえば、スタック全体に複数の MainWindows がある場合、必要に応じてハンドラーからアクセスできる、それらすべてへのポインターのグローバル ベクトルを使用することもできます。

kill foo一般的な kill ( など) の場合、SIGKILL ではなく SIGQUIT が返されることに注意してください。SIGQUIT は問題なく無視できます。SIGKILL は専用ですkill -9 foo(この場合、ユーザーはクリーンアップを行うことさえ望まないかもしれません)。

はい、信号は毛むくじゃらです。

編集 - SIGKILL は無視できないだけでなく、キャッチできないことも知らされました。実際、SIGKILL でできる正気なことはほとんどありません。一時ディレクトリを削除しますか? なんで?その一時ディレクトリには理由があります。

リンク解除について他の人がコメントしたように、特定のハックを実行できない限り、sigkill が停電であるふりをして、次の起動時に回復します。

それは私が私のお尻から話すために得るものです。

于 2009-01-25T16:52:50.687 に答える
0

プロセスが強制終了された場合 (タスク マネージャーなどから)、クリーンアップを行う方法はありません。

プログラムが停止した場合、他のプロセスがそのクリーンアップを行う必要があります。そのプロセスを開始し、プログラムをその子プロセスとして起動します。このプロセスは、プログラムの開始前に一時ディレクトリを作成し、プログラムの終了後に削除します。

ただし、ラッパープロセスが強制終了された場合、これでも問題は解決しません。

于 2009-01-25T16:31:09.653 に答える