2010-03-13 11 views
7

मुझे मिली क्रैश रिपोर्टर ढांचे में से एक ऐसा करता है: यदि ऐप के लिए ~/लाइब्रेरी/लॉग/क्रैश रिपोर्टर फ़ोल्डर में क्रैश रिपोर्ट मौजूद है, तो यह निर्धारित करता है कि एक क्रैश पहले हुआ था। फिर यह उपयोगकर्ता को डेवलपर को क्रैश लॉग भेजने की अनुमति देता है। और अंत में, यह उन लॉग को हटा देता हैलॉन्च होने पर, यह निर्धारित करने के लिए कि क्या ऐप ने आखिरी बार इसे छोड़ दिया था?

यह विलोपन है जो मुझे परेशान कर रहा है। यह मेरे लिए स्वीकार्य नहीं है। शायद उपयोगकर्ता बाद में उन लॉग को देखना चाहता है। उपयोगकर्ता को बस अपने क्रैश लॉग को हटाने के लिए यह मुश्किल है।

तो मैं दुर्घटना निर्धारित करने के लिए एक बेहतर तरीका ढूंढ रहा हूं।

यह वास्तव में उपयोगकर्ता डिफ़ॉल्ट या उपयोगकर्ता डेटा में अंतिम पढ़ने वाले क्रैश लॉग को संग्रहीत करने के लिए काम नहीं करता है, क्योंकि इसका अर्थ यह होगा कि यदि उपयोगकर्ता डेटा और डिफ़ॉल्ट को हटा देता है (जिसे उसके पास तब भी करने का अधिकार है जब वह या वह चाहती है), और उसके बाद ऐप लॉन्च करेगी, यह पता चला होगा कि आखिरी बार इसे छोड़ दिया गया था। तो यह काम नहीं करता है।

कोई विचार?

उत्तर

2

प्रत्येक बार बाहर निकलने पर फ़ाइल को लिखें। हर बार जब आप प्रोग्राम खोलते हैं तो उस फ़ाइल को पढ़ें। प्रत्येक बार कार्यक्रम समाप्त होने पर फ़ाइल के लिए एक विशिष्ट पूर्णांक लिखें जिसे प्रोग्राम शुरू होने पर हर बार पढ़ा जाता है।

उदाहरण के लिए यदि 0 ऐसी फ़ाइल में लिखा गया है जो गैर-क्रैश को इंगित कर सकता है। कुछ और एक दुर्घटना का प्रतीक है।

+1

हम्म? और मैं यह फाइल कहां लिखूंगा? क्या आप सुनिश्चित हैं कि ऐप विलुप्त हो जाएगा या इस तरह की अधिसूचना विधियों * क्रैश * से पहले? और यहां तक ​​कि अगर ऐसा होता है, तो इनमें से कोई भी विलुइट विधियों में वास्तव में एक पैरामीटर होता है जिसमें कहा गया है कि ऐप क्रैश हो रहा है या क्रैश नहीं हो रहा है? – Enchilada

+1

ओह, मुझे लगता है कि मैं आपको प्राप्त करता हूं। आपका मतलब है कि उपयोगकर्ता डिफ़ॉल्ट में केवल सफल क्यूइट डालें, जो हमेशा सफल छोड़ने पर 1 पर सेट होता है, डिफ़ॉल्ट रूप से 0 होता है, और ऐप लॉन्च होने के बाद -1 पर सेट हो जाता है। और फिर यदि यह वास्तव में -1 लॉन्च करने पर है तो इसका मतलब है कि मुझे क्रैश होना चाहिए। ऐसा कुछ? – Enchilada

+0

हां, और किसी स्थान पर फ़ाइल को पढ़ने/लिखना आपके ऊपर है। –

0

यह एक पुरानी पोस्ट है, लेकिन मैं ऐसा करने का एक अच्छा तरीका ढूंढ रहा था और एक में नहीं आया।

शायद यह .. इसी तरह की स्थिति में किसी को मदद मिलेगी

मैं विंडोज पर यह कर रहा हूं, लेकिन शायद यह भी, OSX/लिनक्स नामित pthread mutexes के प्रयोग पर संभव है कि मैं पर नीति नहीं जानते यदि कोई ऐप समाप्त हो जाता है, तो इस तकनीक के लिए महत्वपूर्ण कौन सा म्यूटेक्स प्रबंधित किया जाता है।

  • अनुप्रयोग 1 रन:

    एक भी ध्वज का उपयोग कर के साथ समस्या यह है कि यह स्थिति में काम नहीं करता है, जहां आवेदन के कई उदाहरण हो सकता है। 'सही ढंग से ध्वज बंद नहीं किया गया है' सेट करता है।

  • ऐप 2 रन। लगता है कि यह बंद नहीं हुआ है क्योंकि ध्वज सेट है और सोचता है कि वहां कोई दुर्घटना नहीं थी।

यह चारों ओर पाने के लिए थोड़ा मुश्किल है और वहाँ शायद ऐसा करने के कई तरीके हैं, लेकिन इस विधि (Windows पर कम से कम) अब तक ठीक काम करने के लिए प्रकट होता है:

एक के साथ एक वैश्विक नामित म्युटेक्स बनाएं नाम के रूप में नव निर्मित GUID/UUID।
GUID ऐप के प्रत्येक उदाहरण के लिए अलग है, इसलिए प्रत्येक के पास एक अद्वितीय नामित म्यूटेक्स होगा। GUID एक फ़ाइल में लिखा गया है जिसमें GUID की एक सूची है। यदि एप्लिकेशन सही ढंग से बंद हो जाता है तो आप फ़ाइल से GUID को हटाते हैं और म्यूटेक्स बंद हो जाता है। यदि एप्लिकेशन क्रैश हो जाता है या समाप्त हो जाता है तो GUID को फ़ाइल से हटाया नहीं जाता है लेकिन ऐप के बिना म्यूट को ओएस द्वारा नष्ट कर दिया जाता है।

जब आप ऐप शुरू करते हैं, तो आप सूची में GUID को चला सकते हैं और उन पर OpenMutex को कॉल कर सकते हैं और mutexes जो मौजूद नहीं हैं (GetLastError ERROR_FILE_NOT_FOUND लौटाता है)।कोई गैर-मौजूदा म्यूटेक्स इंगित करता है कि एक क्रैश/समाप्ति हुई। इस GUID जिनके पास इस संपत्ति है, को इस बिंदु पर सूची से हटाया जा सकता है।

एक अतिरिक्त चीज जो आप कर सकते हैं वह है जब आप सही तरीके से बंद करते हैं तो सूची से खराब GUID को निकालना है। यह निम्न स्थिति के आसपास हो जाता है:

  • अनुप्रयोग 1
  • अनुप्रयोग 2
  • अनुप्रयोग 1 दुर्घटनाओं
  • अनुप्रयोग 2 शुरू होता है सफलतापूर्वक
  • अनुप्रयोग 3 बंद हो जाता है शुरू कर दिया है शुरू होता है।

जब ऐप 3 शुरू होता है, तो यह पोस्ट नहीं करना चाहिए कि एक क्रैश था, क्योंकि अंतिम शट डाउन अच्छा था।

मैंने GUID युक्त फ़ाइल तक पहुंच प्राप्त करने के लिए एक प्रकार का स्पिनलॉक भी लागू किया जो टाइमआउट अवधि के बाद आगे बढ़ेगा और फ़ाइल में ऐप ग्रिड नहीं जोड़ता है। ऐसे मामलों में ऐप को चलाने के बजाए ऐप को किसी भी तरह से चलाने और दुर्घटना का पता लगाने के लिए शायद सबसे अच्छा है।

रेस स्थितियों से बचने के लिए फ़ाइल को पूछताछ और अद्यतन करते समय अन्य चेतावनी फ़ाइल लॉक पर पकड़ना है। विंडोज़ पर, यह stl filestreams के उपयोग को रोकता है, क्योंकि फ़ाइल को अनन्य एक्सेस बनाए रखने के दौरान आपको इसे पढ़ने के बाद फ़ाइल को छोटा करने की आवश्यकता होगी।

1

मैं इसे इस तरह से (रजिस्ट्री प्रत्येक अनुप्रयोग शुरू करने के लिए, हालांकि पहुंच की जानी चाहिए) हल:

@implementation ICNRegistry 

/** 
* @public 
* @date edited 2014-04-28 
*/ 
+ (ICNRegistry*) registry { 

    static ICNRegistry* registrySingleton = nil; 

    @synchronized(self) { 

     if (!registrySingleton) { 

      registrySingleton = [[ICNRegistry alloc] initPrivate]; 
     } 

     return registrySingleton; 
    } 
} 

#pragma mark - 
#pragma mark Initialization 

/** 
* @private 
* @date edited 2014-05-09 
*/ 
- (id) initPrivate { 

    self = [super init]; 

    if (self) { 

     _appQuitSuccessfulIndicatorFilePath = 
     [[self cacheRootForClass:[self class]] stringByAppendingPathComponent: 
     @"didQuitSuccessfullyIndicator"]; 
      // (implementation of cacheRootForClass not included) 

     // Set _lastAppQuitWasSuccessful: 
     [self readPreviousAppSuccessStatusAndStartMonitoringCurrentLaunchQuit]; 

     // Start monitoring app quit: 
     [[NSNotificationCenter defaultCenter] addObserver:self selector: 
     @selector(registerAppWillQuitSuccessfully) name: 
     UIApplicationWillTerminateNotification object:nil]; 
    } 

    return self; 
} 

#pragma mark - 
#pragma mark Monitoring App Quits 

/** 
* @private 
* Checks if a file exists at a specific location. If the file exists, then 
* last app quit was successful and lastAppQuitWasSuccessful will be set to YES. 
* Otherwise, if the file does not exist, lastAppQuitWasSuccessful will be set 
* to NO. 
* 
* @discussion 
* When app quits in a normal way, a file will be created on app termination, that 
* way indicating successful quit. If the app quits unexpectedly, then the file 
* will not be written and thus the quit will be indicated as not being successful. 
* 
* @since 2014-05-09 
* @date edited 2014-05-09 
*/ 
- (void) readPreviousAppSuccessStatusAndStartMonitoringCurrentLaunchQuit { 

    NSFileManager* fm = [NSFileManager defaultManager]; 

    self.lastAppQuitWasSuccessful = NO; 

    if ([fm fileExistsAtPath:self.appQuitSuccessfulIndicatorFilePath]) { 

     self.lastAppQuitWasSuccessful = YES; 

     NSError* error; 
     [fm removeItemAtPath:self.appQuitSuccessfulIndicatorFilePath error:&error]; 

     if (error) { 

      ICN_WARN(@"failed to delete 'app quit successful' indicator file at " 
        @"path %@; %@", self.appQuitSuccessfulIndicatorFilePath, 
        error.localizedDescription); 
     } 
    } 
} 

/** 
* @private 
* @since 2014-05-09 
* @date edited 2014-05-09 
*/ 
- (void) registerAppWillQuitSuccessfully { 

    NSFileManager* fm = [NSFileManager defaultManager]; 

    // Create file path if not present: 
    NSError* error; 
    NSString* dir = [self.appQuitSuccessfulIndicatorFilePath 
        stringByDeletingLastPathComponent]; 
    [fm createDirectoryAtPath:dir withIntermediateDirectories:YES 
        attributes:nil error:&error]; 

    if (error) { 

     ICN_WARN(@"failed to create dir %@; %@", dir, error.localizedDescription); 
     return; 
    } 

    [fm createFileAtPath:self.appQuitSuccessfulIndicatorFilePath 
       contents:nil attributes:nil]; 
} 

#pragma mark - 

@end 

फिर, उदाहरण के लिए, मेरे ऐप प्रतिनिधि में मैं कुछ इस तरह करते हैं:

- (BOOL) application:(UIApplication*)application 
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { 

    // If app did quit unexpectedly (due to crash, reset, etc) last time it was 
    // used, then clear all cache to avoid inconsistencies 
    if (![[ICNRegistry registry] lastAppQuitWasSuccessful]) { 

     [ICNUIViewImageCache clearCache]; 
    } 
} 

यह ध्यान दिया जाना चाहिए कि इस समाधान के साथ, पहली बार ऐप लॉन्च होने पर यह पता लगाया जाएगा कि इससे पहले दुर्घटना हुई थी। यदि यह कोई समस्या है, तो फ़ाइल संकेतक पहली बार ऐप लॉन्च होने पर बनाया जा सकता है।

संबंधित मुद्दे