単純な Web サーバーを実行するサブプロセスを開始するアプリケーションを作成しています。私は NSTask を使用しており、パイプを使用して通信していますが、すべてが多かれ少なかれ問題ないようです。ただし、プログラムがクラッシュした場合、サブプロセスは生きたままになり、次にアプリを起動すると、古いサブプロセスと新しいサブプロセスの間で競合が発生します。所有しているアプリが終了したときにサブプロセスが終了するようにする方法はありますか?
5 に答える
上記のどれも機能しません...launchd
文書化されていないほど複雑であっても、この一般的なシナリオを処理する方法はありません。Apple がバックグラウンド プロセスを実行するための「マザーシップ承認済み」の方法を作成しない理由はわかりませんが、私の解決策は…
NSTask を介してシェル スクリプトを起動し、必要な変数を渡します。 また、親プロセスの PIDを etc経由 で渡します
int masterPID = [[NSProcessInfo processInfo] processIdentifier];
。これらをスクリプトで $1、$2 などを介して読み取ります。次に、スクリプト内からサブプロセスを起動します..
スクリプト内でサブプロセスと親プロセスの両方を監視します。
これには二重の目的があります..「子供たちを監視する..」ことができます..そして、親の死(または恐ろしい自動車事故)の悲しい出来事では 、ゾンビの孤児を殺します.. 次に、自分でトリガーを引くと(シェルスクリプトである)、プロセステーブルがクリーンになります。あたかも存在しなかったかのように。ブロックされたポート、再起動時の競合、アプリ ストアの拒否はありません。これが役立つかどうかを教えてください!
更新: Xcodeテンプレート/デーモン/プロジェクト/トリックを行うものを作成しました。それをチェックしてください.. mralexgray / Infanticide。
アプリケーション デリゲートは、
- (void)applicationWillTerminate:(NSNotification *)aNotification
メッセージを送信し、そこで NSTask を終了します。ただし、クラッシュ時にこのデリゲートが呼び出されるとは限りません。
次の 2 つの追加手順を実行できます。
- 作成時にサブプロセスの PID をディスクに書き込み、通常のシャットダウン時にそれを削除することにより、新しい親プロセスの起動中に既存の孤立したサブプロセスをシャットダウンします (最も安全な動作ではない場合があります)。
- NSPipe のエンドポイントが特定の時間 (ハートビートのようなもの) の間データを送信しなかった場合は、サブプロセスをシャットダウンします。
更新:これを適切に確認するようになったので、機能しません。プロセス グループを設定しようとすると、このエラーで失敗します。
EPERM 「要求されたプロセスの実効ユーザー ID が呼び出し元のものと異なり、プロセスは呼び出しプロセスの子孫ではありません。」
この問題に関する最新のスレッドがありますが、私が知る限り簡単な解決策はありません
http://www.omnigroup.com/mailman/archive/macosx-dev/2009-March/062164.html
アプリで Cocoadev に関する Robert Pointon の提案を試しました。私はまだそれをテストする準備ができていません。
http://www.cocoadev.com/index.pl?NSTaskTermination
アイデアは、タスクのプロセス グループを、タスクを起動するプロセスのプロセス グループと同じに設定することです (注: 以下のコードは、基本的に上記のスレッドから持ち上げたものです)。
pid_t group = setsid();
if (group == -1) {
group = getpgrp();
}
[task launch];
if (setpgid([task processIdentifier], group) == -1) {
NSLog(@"unable to put task into same group as self");
[task terminate];
} else {
// handle running task
}