2015-04-25 8 views
15

हमारे पास हमारे ऐप में CMMotionManager का एक उदाहरण है जिसका उपयोग हम 5 हर्ट्ज की आवृत्ति पर सेंसर अपडेट प्राप्त करने के लिए करते हैं। निम्नलिखित कोड है जो हम गति अद्यतन शुरू करने के लिए उपयोग करते हैं:रोकथाम पर कोरमोशन क्रैश (आईपैड-केवल) StopDeviceMotionUpdates

[self.motionManager 
startDeviceMotionUpdatesUsingReferenceFrame: 
CMAttitudeReferenceFrameXMagneticNorthZVertical 
toQueue:operationQueue 
withHandler:^(CMDeviceMotion *motion, NSError *error) { 
if (!error) { 
    [self doSomethingWithMotion:motion]; 
} else { ... } 

उपर्युक्त विधि हमेशा मुख्य धागे पर आती है।

अब, एक बार हम अपने कार्य के साथ किया जाता है, हम प्रस्ताव अद्यतन निम्न विधि को फोन करके, फिर मुख्य थ्रेड पर रोक:

- (void)stopMotionUpdates { 
    // This might get called on concurrent threads. 
    // So better using sync block + make it idempotent 
    @synchronized(self) { 
     if (_motionManager.deviceMotionActive) { 
      [_motionManager stopDeviceMotionUpdates]; 
      _prevPoint = nil; 
     } 
    } 
} 

मुद्दा हम सामना कर रहे हैं यह है कि stopMotionUpdates क्रैश, वह भी केवल आईपैड में। हमने आईफोन और आईपैड पर विभिन्न ओएस संस्करणों के साथ बड़े पैमाने पर इसका परीक्षण किया है और हमें केवल आईओएस 7 और आईओएस 8 दोनों के लिए आईपैड (मिनी 1,2 और रेटिना/गैर-रेटिना) पर क्रैश मिलता है। साथ ही, हम परीक्षण के लिए उपयोग किए जाने वाले सभी आईपैड पर क्रैश को पुन: पेश नहीं कर सकते हैं, लेकिन केवल कुछ ही। अनुसरण कर रहे हैं मुख्य और दुर्घटनाग्रस्त हो गया थ्रेड के लिए दुर्घटना लॉग:

Thread : com.apple.main-thread 
0 libsystem_kernel.dylib   0x00000001935f1cdc semaphore_wait_trap + 8 
1 libdispatch.dylib    0x00000001934fbb3c _dispatch_semaphore_wait_slow + 252 
2 CoreMotion      0x0000000186bf67d4 (null) 
3 CoreMotion      0x0000000186be3698 (null) 
4 MyApp       0x00000001002f7434 -[MyAppMotionManager stopMotionUpdates] 
... 
... 
12 MyApp       0x00000001002e94f8 __getDispatchTimer_block_invoke 
13 libdispatch.dylib    0x00000001934f3fd4 _dispatch_client_callout + 16 
14 libdispatch.dylib    0x00000001934f5b90 _dispatch_source_invoke + 500 
15 libdispatch.dylib    0x00000001934f7180 _dispatch_main_queue_callback_4CF + 244 
16 CoreFoundation     0x00000001864fec2c __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12 
17 CoreFoundation     0x00000001864fcf6c __CFRunLoopRun + 1452 
18 CoreFoundation     0x000000018643dc20 CFRunLoopRunSpecific + 452 
19 GraphicsServices    0x000000018c0ddc0c GSEventRunModal + 168 
20 UIKit       0x000000018956efdc UIApplicationMain + 1156 
21 MyApp       0x00000001000c9850 main (main.m:14) 
22 libdyld.dylib     0x000000019350faa0 start + 4 

EXC_BREAKPOINT UNKNOWN at 0x0000000186c257ac 
Thread : Crashed: Thread 
0 CoreMotion      0x0000000186c257ac (null) + 110504 
1 CoreMotion      0x0000000186c25774 (null) + 110448 
2 CoreMotion      0x0000000186bf3c84 (null) 
3 CoreMotion      0x0000000186bf67ec (null) 
4 CoreMotion      0x0000000186bf3b80 (null) 
5 CoreMotion      0x0000000186c24c48 (null) + 107588 
6 CoreMotion      0x0000000186bf67ec (null) 
7 CoreMotion      0x0000000186c24ba4 (null) + 107424 
8 CoreMotion      0x0000000186be3b9c (null) 
9 CoreMotion      0x0000000186bf6860 (null) 
10 CoreFoundation     0x00000001864ff680 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 20 
11 CoreFoundation     0x00000001864fe838 __CFRunLoopDoBlocks + 300 
12 CoreFoundation     0x00000001864fd0a4 __CFRunLoopRun + 1764 
13 CoreFoundation     0x000000018643dc20 CFRunLoopRunSpecific + 452 
14 CoreFoundation     0x00000001864932a8 CFRunLoopRun + 112 
15 CoreMotion      0x0000000186bf653c (null) 
16 libsystem_pthread.dylib  0x000000019368be1c _pthread_body + 168 
17 libsystem_pthread.dylib  0x000000019368bd74 _pthread_body 

हम प्रस्ताव अद्यतन हैंडलर ब्लॉक में आत्म संदर्भ के बाद से, वस्तु पूरे कतार तक पुनः आवंटित की जाती नहीं किया जाना चाहिए प्लावित है। किसी भी मदद की सराहना की है :)

उत्तर

2

आपका दुर्घटना @synchronized निर्देश से आता है। जैसा कि आप देख सकते हैं कि मुख्य धागा @synchronized में आपका कोड निष्पादित कर रहा है। यह व्यू कंट्रोलर को किसी अन्य थ्रेड द्वारा एक्सेस करने से रोकता है।

क्रैश किया गया थ्रेड कोरमोशन के लिए है और मुझे लगता है कि यह डिवाइस गति पर अपडेट देने का प्रयास कर रहा था।

मेरा मानना ​​है कि क्रैश कुछ मामलों में हो रहा है जब कोरमोशन उसी समय अपडेट करने का प्रयास करता है जब आपका मुख्य थ्रेड सिंक्रनाइज़ किया जाता है।

+0

stopMotionUpdates विधि एक ViewController में नहीं है, मैं एक अलग MotionManager कि हैंडलिंग की देखभाल और प्रतिनिधियों के लिए गति डेटा पहुंचाने लगता है। जब भी गति डेटा आवश्यकता समाप्त होती है तो हम stopMotionUpdates को कॉल करते हैं। @synchronized इस मामले में कोई म्यूटेक्स लॉक नहीं बना रहा है। –

+0

मुझे आपके साथ असहमत होना है क्योंकि जब आप दुर्घटना का सामना करते हैं तो आपका मुख्य धागा लॉक होता है (semaphore_wait_trap)। – pteofil

+0

यह समस्या है, मैं अपने कोड में कहीं भी मुख्य धागे को लॉक नहीं कर रहा हूं। तो, ऐसा लगता है कि यह CoreMotion के अंदर कहीं से बंद हो रहा है। और दुर्घटना वॉचडॉग टाइमआउट नहीं है। क्या आपको यकीन है कि इस प्रकार का दुर्घटना भी डेडलॉक के कारण होता है? –

4

आप मुख्य थ्रेड ओवरलोड कर रहे हैं।

  • एक सामान्य नियम के रूप में, आप मुख्य थ्रेड तुलना में या एक दूसरे के बारे में अधिक लेता है पर कुछ भी कभी नहीं करना चाहिए।

  • मुख्य धागा उपयोगकर्ता इंटरफ़ेस चलाने के लिए ज़िम्मेदार है। यदि आप किसी भी महत्वपूर्ण समय के लिए मुख्य धागे को अवरुद्ध करते हैं, तो उपयोगकर्ता इंटरफ़ेस अस्वीकार्य रूप से अनुत्तरदायी हो जाता है।

  • वॉचडॉग - उपयोगकर्ता इंटरफ़ेस को उत्तरदायी रखने के लिए, आईओएस में वॉचडॉग तंत्र शामिल है। यदि आपका एप्लिकेशन समय में कुछ उपयोगकर्ता इंटरफ़ेस ईवेंट (लॉन्च, निलंबित, फिर से शुरू, समाप्त) का जवाब देने में विफल रहता है या कुछ ऑपरेशन मुख्य थ्रेड पर थोड़ा और समय लेता है तो वॉचडॉग आपके एप्लिकेशन को मार देगा। वॉचडॉग आपको कितनी बार औपचारिक रूप से दस्तावेज नहीं देता है, लेकिन यह हमेशा कम होता है।

  • ऐसी कोई भी आपरेशन के लिए एक पृष्ठभूमि धागे पर किया जाना चाहिए और आप आसानी से इसे

    का उपयोग करते हैं सकता है
    • dispatch_async

    • NSOperationQueue

    • performSelectorInBackground

उम्मीद है कि इससे मदद मिलती है।

+0

यहाँ किसी को 'ब्लूटूथ के साथ semaphore_wait_trap' का सामना करना पड़ा और का उपयोग कर समस्या के समाधान मिल गया है' dispatch_async' http://goo.gl/PumFrT –

+0

आप "semaphore_wait_trap" watchdoc टाइमआउट के कारण होती है कि यकीन है? मैं सिर्फ यूआई थ्रेड में stopMotionUpdates को बुला रहा हूं और मुख्य धागे में कोई भारी ऑपरेशन नहीं हो रहा है। –

+0

मैं बहुत ज्यादा यकीन नहीं है लेकिन यह यह that.Don't मुख्य सूत्र में कुछ भी है कि 'खत्म करने के लिए stopDeviceMotionUpdates' लिया UI.What के औसत या अधिक से अधिक समय को प्रभावित नहीं करता कॉल करने के लिए अग्रणी हो सकता है? क्या आप कोड को किसी अन्य थ्रेड में ले जा सकते हैं और कोशिश कर सकते हैं? क्या आप 'dispatch_async' कोशिश कर सकते हैं? –

1

आप कहाँ परिभाषित करते हैं 'operationQueue' वहाँ कोई आत्म है, इसलिए मैं इसे एक वर्ग स्तर चर नहीं है संभालने हूँ। आप चाहते हैं कि एक मजबूत संदर्भ के साथ एक वर्ग संपत्ति हो, इसलिए अपडेट प्राप्त करते समय इसे अस्वीकार नहीं किया जाता है। मैंने यह भी देखा है कि यह ब्लूटूथ कॉल पर dispatch_queue_t के लिए फ़ंक्शन स्कोप्ड चर के साथ होता है।

मेमोरी प्रबंधन अनियमित व्यवहार की व्याख्या करेगा, लेकिन आप हमेशा आईपैड पर वेबसाइट टैब का एक गुच्छा अन्य आईपैड खोलकर आईओएस को अधिक आक्रामक बनाने की कोशिश कर सकते हैं, जिसे आपने पहले देखा था।

CMMotion अद्यतन एक फीफो क्रम ताकि समझा सकता है कारण है कि आप लॉग में semaphore_wait_trap देखने के सही होने की में काम करने के लिए मिला है।

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