我正在編寫一個啓動運行簡單Web服務器的子進程的應用程序。我正在使用NSTask並用管道與它進行通信,並且一切看起來都很不錯。但是,如果我的程序崩潰了,子進程將保持活動狀態,下次啓動應用程序時,舊子進程和新子進程之間會發生衝突。有沒有什麼方法可以確保子進程在擁有的應用程序死亡時死亡?確保子進程在Cocoa中死亡
回答
您的應用程序委託可以實現
- (void)applicationWillTerminate:(NSNotification *)aNotification
消息,並終止NSTask那裏。但是,不能保證在發生崩潰時這個代表將被調用。你可以採取
兩個額外的步驟:
- 關機推出一個新的父進程的過程中現有的,孤立子寫下磁盤的PID上創建子進程和正常的關機過程中移除(有時不是最安全的行爲)。
- 如果NSPipe的終點沒有在特定時間內發送數據(如心跳),則關閉子流程。
更新:現在,我去檢查這適當它不起作用。嘗試設置進程組失敗並出現此錯誤;
EPERM「請求進程的有效用戶標識與調用方的有效用戶標識不同,進程不是調用進程的後代。」
有關於這個問題,但沒有簡單的解決方案更近的線程,據我可以告訴
http://www.omnigroup.com/mailman/archive/macosx-dev/2009-March/062164.html
我已經試過由羅伯特·普安頓上Cocoadev建議在我的應用程序。儘管如此,我還沒有去測試它。
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詳細記錄,複雜性的方式來處理這種常見的場景。我不知道爲什麼蘋果不只是做一個「母船批准」的方式來運行後臺進程,但無論..我的解決辦法是...
啓動一個shell腳本,通過NSTask,並通過它,你需要的任何變量。 另外在你的父進程的PID通過
int masterPID = [[NSProcessInfo processInfo] processIdentifier];
等傳遞通過$ 1,$ 2,等等。閱讀這些腳本中的反過來,從腳本內啓動你的子過程..
監視腳本中的父進程的子進程和。
這有兩個目的..它使您能夠「在孩子們保持眼睛..」,並在parentcide(或可怕的車禍)的不幸的事件 - 殺客殭屍孤兒。然後,你自己拉起扳機(,你是shell腳本),你的工藝表將被清理乾淨。就好像你從未存在過。沒有阻塞的端口,在重新啓動時沒有衝突,沒有應用商店拒絕。讓我知道這是否有幫助!
更新:我做了一個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. 確保子進程在退出Python程序時死亡
- 2. 追蹤子進程的死亡
- 3. 進程已經死亡
- 4. Node.js進程在aws實例上死亡
- 5. WCF tcp連接在進程死亡時保持打開狀態
- 6. android遠程進程(receiver)快速死亡
- 7. Erlang:進程保持鏈接到死亡線程
- 8. 分叉多個孩子,等到孩子進程死亡
- 9. 父進程如何找到導致其子進程死亡的進程的PID?
- 10. 確定過程是否已經死亡?
- 11. IPC:共享內存死亡進程notfication
- 12. Shell腳本進程自動死亡
- 13. Nohup java進程超時或死亡
- 14. Jsch退出後進程死亡
- 15. Android進程已經死亡後背景
- 16. SQLAlchemy - 插入> 1M行 - 進程死亡
- 17. 進程死亡 - 刪除輸出文件?
- 18. 當python進程死亡時運行atexit()
- 19. ActivityManager進程已經死亡問題
- 20. node.js進程何時意外死亡?
- 21. 在python線程死亡時?
- 22. 從`setuid`進程中檢測父進程的死亡
- 23. 當應用程序死亡時殺死外部進程
- 24. Ajax Perl Catalyst FastCGI子進程不會死亡
- 25. 如果父母死亡,子進程不會自殺
- 26. 死亡與羊羣,叉子和終止父進程
- 27. 我怎麼知道孩子進程何時死亡?
- 28. 保持Beanshell中死亡變量
- 29. SSRS - 進程在不使用後死亡/進入睡眠狀態
- 30. 亞馬遜Linux實例在Python腳本中使用子進程死亡。運行
您是否嘗試過讓你的程序不會崩潰? :D – kubi 2009-08-18 21:00:06
我正在考慮Atlas這裏^^ – 2010-01-25 00:19:28
您可以嘗試在Launchd中運行Web服務器。至少這樣,當你的應用程序崩潰並重新啓動時,Launchd會告訴你服務器已經在運行,所以你可以關閉它並重新啓動它,如果你想的話。 – 2012-01-07 22:14:58