単純なWebサーバーを実行しているサブプロセスを起動するアプリケーションを作成しています。私はNSTaskを使用しており、パイプで通信しています。しかし、私のプログラムがクラッシュした場合、サブプロセスは生き残ります。次回にアプリケーションを起動すると、古いサブプロセスと新しいサブプロセスの間に競合が発生します。所有アプリが死んだときにサブプロセスが確実に消滅するような方法はありますか?サブプロセスがココアで死んでいることを確認してください
答えて
アプリケーションデリゲートは
- (void)applicationWillTerminate:(NSNotification *)aNotification
メッセージを実装し、そこNSTaskを終了することができます。ただし、クラッシュ中にこの代理人が呼び出されることは保証されていません。
あなたが取ることができる2つの追加手順:
- シャットダウン作成上のディスクにサブプロセスのPIDを書き留め、通常のシャットダウン時に、それを除去することにより、新しい親プロセスの起動時に既存の、孤立したサブプロセス(ときどき最も安全な行動ではない)。
- NSPipeのエンドポイントが特定の時間(ハートビートのようなもの)のデータを送信しなかった場合、サブプロセスをシャットダウンします。
更新:これを正しくチェックするようになったので、正しく動作しません。プロセスグループを設定しようとすると、このエラーで失敗します。
EPERM "要求されたプロセスの実効ユーザーIDが呼び出し元のユーザーIDと異なり、プロセスが呼び出しプロセスの子孫ではありません。"
この問題の詳細最近のスレッドが、私の知る限り、私は私のアプリでCocoadevのロバート・Pointonの提案を試してみた
http://www.omnigroup.com/mailman/archive/macosx-dev/2009-March/062164.html
を言うことができるように簡単な解決策があります。私はまだそれをテストすることに慣れていない。
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
}
なし...さえlaunchd
すべてで、それはcrappily文書化・複雑だが、この一般的なシナリオを処理する方法がありません。私はAppleがちょうどバックグラウンド・プロセスを実行するための「母船-承認」の方法を確認しない理由を知らないが、何でも...私の解決策がある...
起動シェルスクリプトをNSTask経由し、それをあなたが必要とするすべての変数を渡します。 また...ターンでは、スクリプト内部からあなたのサブプロセスを起動
$ 1、$ 2等を介して、あなたのスクリプトでこれらを読むなど
int masterPID = [[NSProcessInfo processInfo] processIdentifier];
を経由して、あなたの親プロセスのPIDに渡すスクリプト内の親プロセスであるサブプロセスとを監視します。
これは、「子供たちに目を離さない..」することができます、そしてparentcide(または恐ろしい車の事故)の悲しい出来事に...二重の目的を果たす - キルオフゾンビ孤児を。その後、あなたは(あなたがシェルスクリプトさ)自分で引き金を引くと、あなたがを決して存在しなかったかのように、あなたのプロセステーブルが.. きれいになります。ブロックされたポートはなく、再起動時に競合はなく、アプリストアの拒否はありません。 Lemmeがこれを助けるかどうかを知る!
更新:私は、Xcodeのテンプレート/デーモン/プロジェクト/何でもそのトリックを行いました。それを確認してください.. mralexgray/Infanticide.
次のコードサンプルはあなたに役立ちます。それはhereから借りている
、
#include <CoreFoundation/CoreFoundation.h>
#include <unistd.h>
#include <sys/event.h>
static void noteProcDeath(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) {
struct kevent kev;
int fd = CFFileDescriptorGetNativeDescriptor(fdref);
kevent(fd, NULL, 0, &kev, 1, NULL);
// take action on death of process here
printf("process with pid '%u' died\n", (unsigned int)kev.ident);
CFFileDescriptorInvalidate(fdref);
CFRelease(fdref); // the CFFileDescriptorRef is no longer of any use in this example
}
// one argument, an integer pid to watch, required
int main(int argc, char *argv[]) {
if (argc < 2) exit(1);
int fd = kqueue();
struct kevent kev;
EV_SET(&kev, atoi(argv[1]), EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
kevent(fd, &kev, 1, NULL, 0, NULL);
CFFileDescriptorRef fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd, true, noteProcDeath, NULL);
CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
CFRunLoopSourceRef source = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopDefaultMode);
CFRelease(source);
// run the run loop for 20 seconds
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 20.0, false);
return 0;
}
- 1. ANTでポートが開いていることを確認してください
- 2. アクティブであることを確認してください
- 3. 重複がないことを確認してください
- 4. matlabで行列がNanでないことを確認してください
- 5. Jinja2で配列が空であることを確認してください
- 6. ターゲットブランチでPRが最新であることを確認してください
- 7. スライダがSelenium Webdriverでスライドできることを確認してください
- 8. Nunjucksでオブジェクトが空であることを確認してください
- 9. vb.netでDatagridviewが空であることを確認してください
- 10. プロパティがラムダ式でヌルであることを確認してください
- 11. Rubyでディレクトリが空であることを確認してください
- 12. RTMP:Pythonでストリームがオンラインであることを確認してください
- 13. SwiftでNSFontが太字であることを確認してください
- 14. アプリケーションがフォアグラウンドモードで非アクティブであることを確認してください
- 15. サブモジュールコミットがリポジトリと同じであることを確認してください
- 16. ブランチが実行されていることを確認してください。
- 17. iphone - アプリがインストールされていることを確認してください
- 18. Skypeがインストールされていることを確認してください
- 19. ヘッドセットが挿入されていることを確認してください
- 20. IONICサービスがロードされていることを確認してください。
- 21. プログラムがパイプされていることを確認してください
- 22. ALPNがサポートされていることを確認してください
- 23. キーが押されていることを確認してください。セレン
- 24. PEAR MAILがインストールされていることを確認してください
- 25. ipconfigが適用されていることを確認してください
- 26. mongoDBが接続されていることを確認してください。
- 27. アプリがインストールされていることを確認してください
- 28. ビューが隠されていないことを確認してください。
- 29. ポートが開いていることを確認してください
- 30. material2 sidenavが開いていることを確認してください
は、あなたのプログラムがクラッシュしない作ってみましたがありますか? :D – kubi
ここでAtlasについて考えています^^ –
LaunchdでWebサーバーを実行してみることができます。少なくともそのように、あなたのアプリケーションがクラッシュして再起動したとき、Launchdはサーバーが既に起動しているので、シャットダウンして再起動することができます。 –