2009-08-18 11 views
9

मैं एक ऐसा एप्लीकेशन लिख रहा हूं जो एक सरल वेब सर्वर चलाने वाले उपप्रोसेस को बंद कर देता है। मैं एनएसटीस्क का उपयोग कर रहा हूं और पाइप के साथ इसके साथ संवाद कर रहा हूं, और सबकुछ कम या ज्यादा ठीक लगता है। हालांकि, अगर मेरा प्रोग्राम दुर्घटनाग्रस्त हो जाता है, तो उपप्रजाति जीवित रहती है और अगली बार जब मैं ऐप लॉन्च करता हूं तो पुराने उपप्रोसेस और नए के बीच एक संघर्ष होता है। क्या यह सुनिश्चित करने का कोई तरीका है कि मालिकाना ऐप मरने पर उपप्रोसेस मर जाए?कोको में एक सबप्रोसेस मर चुका है

+0

आप अपने प्रोग्राम क्रैश नहीं बनाने की कोशिश की? : डी – kubi

+0

मैं एटलस के बारे में सोच रहा हूं ^^ –

+0

आप लॉन्चड में वेब सर्वर चलाने का प्रयास कर सकते हैं। कम से कम इस तरह, जब आपका ऐप दुर्घटनाग्रस्त हो जाता है और आप फिर से लॉन्च करते हैं, तो लॉन्चड आपको बताएगा कि सर्वर पहले ही चल रहा है ताकि आप इसे बंद कर सकें और यदि आप चाहें तो इसे पुनरारंभ करें। –

उत्तर

1

आपका आवेदन प्रतिनिधि

- (void)applicationWillTerminate:(NSNotification *)aNotification 

संदेश को लागू है, और वहाँ NSTask समाप्त कर सकते हैं। हालांकि, यह गारंटी नहीं है कि एक दुर्घटना के दौरान, इस प्रतिनिधि को बुलाया जाएगा।

दो अतिरिक्त कदम ले जा सकते हैं:

  • शटडाउन एक मौजूदा, एक नया अभिभावक-प्रक्रिया की शुरुआत होने के दौरान अनाथ उपप्रक्रिया निर्माण पर उपप्रक्रिया की पीआईडी ​​डिस्क पर लिखने और सामान्य शटडाउन के दौरान निकाल कर (कभी-कभी सबसे सुरक्षित व्यवहार नहीं)।
  • एनएसपीआईपी के अंत-बिंदु ने विशिष्ट समय के लिए डेटा नहीं भेजा (दिल की धड़कन की तरह कुछ) के लिए उप-प्रोसेस को बंद कर दिया।
0

अद्यतन: अब जब मैं इसे ठीक से जांचने के लिए जाता हूं तो यह काम नहीं करता है। प्रक्रिया समूह को सेट करने का प्रयास इस त्रुटि के साथ विफल रहता है;

EPERM "अनुरोधित प्रक्रिया की प्रभावी उपयोगकर्ता आईडी कॉलर से अलग है और प्रक्रिया कॉलिंग प्रक्रिया का वंशज नहीं है।"

वहाँ जहाँ तक मैं

http://www.omnigroup.com/mailman/archive/macosx-dev/2009-March/062164.html


बता सकते हैं मैं अपने अनुप्रयोग में Cocoadev पर रॉबर्ट 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 
} 
2

कोई नहीं ... सब में भी नहीं launchd यह crappily से प्रलेखित-जटिलता है इस आम परिदृश्य को संभालने के लिए एक तरीका है। मुझे पता नहीं क्यों एप्पल सिर्फ एक "mothership को मंजूरी दे दी" पृष्ठभूमि प्रक्रियाओं को चलाने के लिए जिस तरह से नहीं है, लेकिन जो कुछ भी .. मेरी समाधान है ...

  1. लॉन्च एक खोल स्क्रिप्ट NSTask के माध्यम से और यह किसी भी के लिए आवश्यक चरों गुजरती हैं। इसके अलावा अपने माता-पिता की प्रक्रिया 'पीआईडी ​​ में पारित int masterPID = [[NSProcessInfo processInfo] processIdentifier]; आदि के माध्यम से $ 1, $ 2, आदि के माध्यम से अपनी स्क्रिप्ट में इन पढ़ें बारी में

  2. , स्क्रिप्ट अंदर से अपने subprocesses लांच ..

  3. स्क्रिप्ट के भीतर आपकी मूल प्रक्रिया दोनों subprocess और दोनों की निगरानी करें।

यह एक दोहरे उद्देश्य से कार्य करता है .. यह "बच्चों पर नजर रखना .." करने में सक्षम बनाता है, और parentcide (या भयानक कार दुर्घटना) के दुखद घटना में - मारने बंद ज़ोंबी अनाथ। फिर, आप ट्रिगर को अपने आप खींचें (आप शेल स्क्रिप्ट) हैं और आपकी प्रक्रिया तालिका साफ़ हो जाएगी .. जैसे कि आप कभी भी मौजूद नहीं थे। कोई अवरुद्ध बंदरगाह नहीं, रिलांच पर कोई संघर्ष नहीं, कोई ऐप-स्टोर अस्वीकृति नहीं। लेमेम जानता है कि यह मदद करता है!

अद्यतन: मैंने एक एक्सकोड टेम्पलेट/डेमन/प्रोजेक्ट/जो कुछ भी चाल किया है। इसे जांचें .. mralexgray/Infanticide.

1

निम्नलिखित कोड नमूना आपको मदद कर सकता है।

यह 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; 
} 
संबंधित मुद्दे