간단한 웹 서버를 실행하는 하위 프로세스를 시작하는 응용 프로그램을 작성하고 있습니다. 나는 NSTask를 사용하고 파이프와 통신하고 있으며, 모든 것이 더 많거나 적은 것으로 보인다. 그러나 내 프로그램이 충돌하면 하위 프로세스가 생존하고 다음에 응용 프로그램을 시작할 때 이전 하위 프로세스와 새 하위 프로세스간에 충돌이 발생합니다. 소유하고있는 앱이 죽을 때 서브 프로세스가 죽는 것을 막을 수있는 방법이 있습니까?코코아에서 서브 프로세스가 죽었는지 확인하십시오.
답변
애플리케이션 위임은
- (void)applicationWillTerminate:(NSNotification *)aNotification
메시지를 구현하고 거기에 NSTask을 종료 할 수 있습니다. 그러나 충돌하는 동안이 대리자가 호출되는 것은 아닙니다.
두 가지 추가 단계는 수행 할 수 있습니다
- 종료 새로운 부모 프로세스의 시작시 기존의 분리 된 서브 프로세스를 생성에 서브 프로세스의 디스크에 아래로 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 문서화 복잡도의이 일반적인 시나리오를 처리 할 수있는 방법이 없습니다. 나는 애플이 단지 백그라운드 프로세스를 실행하는 "모선 승인"방법을하지 않는 이유를 몰라,하지만 어떤 .. 내 솔루션은 ...
시작 쉘 스크립트를 NSTask를 통해 그것에게 당신이 필요로하는 모든 변수를 전달합니다. 또한 .. 차례로, 스크립트 내부 에서 서브 프로세스를 시작
$ 1, $ 2 등을 통해 스크립트에서 이러한 읽기 등
int masterPID = [[NSProcessInfo processInfo] processIdentifier];
을 통해 부모 프로세스의 PID 전달스크립트 내의 하위 프로세스 과을 모두 모니터링하십시오.죽 오프 좀비 고아 -
이것은 ".. 아이들에 눈을 유지"할 수 있습니다, 그리고 parentcide (또는 끔찍한 자동차 사고)의 슬픈 이벤트에 .. 이중 목적을 제공. 그런 다음 트리거를 당겨 (쉘 스크립트) 프로세스 테이블이 깨끗해질 것입니다. 마치 존재하지 않았던 것처럼. 차단 된 포트가 없으며 재발행시 충돌이없고 앱 스토어 거부가 발생하지 않습니다. Lemme이 도움이되는지 알아!
업데이트 : 나는 트릭을하는 Xcode 템플릿/daemon/project/whatever을 만들었습니다. 그것을 밖으로 검사하십시오 .. 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;
}
당신은 당신의 프로그램이 충돌하지 만드는 시도? : D – kubi
여기 아틀라스에 대해 생각하고 있습니다 ^^ –
Launchd에서 웹 서버를 실행할 수 있습니다. 최소한 앱이 충돌하고 다시 실행될 때 Launchd는 서버가 이미 실행 중이므로 종료하고 다시 시작할 수 있음을 알려줍니다. –