26

I am working on a multi-player game in Javascript for the iPad. I am using Smartfox Server for the multiplayer, and Hammer.js for touch events.

I am having an issue where when I use a Hammer event in one particular part of my game, it crashes Mobile Safari. It works completely fine on the PC but on the iPad it's causing a crash.

This is the part of my code where it happens:

this.startButton.hammer().on("tap", this.handleStartClicked);

All that I do in the "handleStartClicked" function is grab the user's name and password from input boxes, save them to local storage (if available), and call the Smartfox "connect" function, which connects the user to Smartfox and begins the login process. Here is the function:

onStartClicked:function(e){
  if(this.nameInput.val() == "" || this.pwInput.val() == "") {return;}

  this.startButton.unbind("click", this.onStartClickBind);

  if(window.localStorage != null && window['localStorage'] != null){
    window.localStorage.username = this.nameInput.val();
    window.localStorage.password = this.pwInput.val();
  }

  this.sfs.connect();

}

If I click the start button, Mobile Safari crashes about 80% of the time. Even if it doesn't crash immediately on that click, it usually crashes at some point later in the game. However, if I never click the start button (for example if I just auto start the user without touch interaction), the crash never happens - not even at later points in the game. I even tried removing the start button completely and just adding the touch listener to the entire document body and it still crashed, so it doesn't seem to have anything to do with the button in particular (it's just a normal HTML Button wrapped in a jQuery object).

The curious thing is that if I change the Hammer.js event to a regular jQuery event:

this.startButton.bind("click", this.onStartClickBind);

Mobile Safari never crashes. Not on the start click...not at any point in the game. It seems to fix everything. The other curious thing is that I'm using Hammer events all over the rest of my code, yet the only spot where it seems to be a problem is on this one handler. I'm at a loss as to what's different about this handler in the game as opposed to any other, unless the crash somehow has to do with the interaction between Mobile Safari, Hammer.js, and Smartfox. I am sending calls to Smartfox on other Hammer handlers in the game though, and they don't crash Safari, so that seems unlikely.

Also, I have the iPad's crash log below, if that sheds anymore light on the issue:

Incident Identifier: 540C3060-271F-468E-9DF8-DA641DACA406
CrashReporter Key:   a5c833f7168137e99d3c8aa6a4d35804a584b7b4
Hardware Model:      iPad3,1
Process:             Web [210]
Path:                /var/mobile/Applications/327316BD-8A50-4245-B728-  
E6504C19A76D/Web.app/Web
Identifier:          com.apple.webapp
Version:             1.0 (1.0)
Code Type:           ARM (Native)
Parent Process:      launchd [1]

Date/Time:           2014-01-13 14:01:50.112 -0800
OS Version:          iOS 7.0.4 (11B554a)
Report Version:      104

Exception Type:  EXC_BREAKPOINT (SIGTRAP)
Exception Codes: 0x0000000000000001, 0x000000000000defe
Triggered by Thread:  4

Thread 0:
0   JavaScriptCore                  0x306a61f2 JSC::JSValue::get(JSC::ExecState*,   
JSC::PropertyName, JSC::PropertySlot&) const + 678
1   JavaScriptCore                  0x3069a5de llint_slow_path_get_by_id + 162
2   JavaScriptCore                  0x3069fbaa llint_op_get_by_id + 132
3   JavaScriptCore                  0x306ab434 JSC::call(JSC::ExecState*, JSC::JSValue,  
JSC::CallType, JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 52
4   WebCore                         0x37787ad2  
WebCore::JSMainThreadExecState::call(JSC::ExecState*, JSC::JSValue, JSC::CallType,   
JSC::CallData const&, JSC::JSValue, JSC::ArgList const&) + 142
5   WebCore                         0x379707bc  
WebCore::JSEventListener::handleEvent(WebCore::ScriptExecutionContext*,   
WebCore::Event*) + 516
6   WebCore                         0x3792edca     
WebCore::EventTarget::fireEventListeners(WebCore::Event*, WebCore::EventTargetData*,  
WTF::Vector<WebCore::RegisteredEventListener, 1ul, WTF::CrashOnOverflow>&) + 482
7   WebCore                         0x3782ea2a   
WebCore::EventTarget::fireEventListeners(WebCore::Event*) + 174
8   WebCore                         0x379e7f24 
WebCore::EventTarget::dispatchEvent(WTF::PassRefPtr<WebCore::Event>) + 60
9   WebCore                         0x380e56e0 
WebCore::WebSocket::didReceiveMessage(WTF::String const&) + 68
10  WebCore                         0x380e7ef0  
WebCore::WebSocketChannel::processFrame() + 2292
11  WebCore                         0x380e71a0  
WebCore::WebSocketChannel::processBuffer() + 80
12  WebCore                         0x380e713c 
WebCore::WebSocketChannel::didReceiveSocketStreamData(WebCore::SocketStreamHandle*, 
char const*, int) + 232
13  WebCore                         0x37fdc5c4    
WebCore::SocketStreamHandle::readStreamCallback(unsigned long) + 236
14  CoreFoundation                  0x2f68f918 _signalEventSync + 116
15  CoreFoundation                  0x2f698ee8 _cfstream_solo_signalEventSync + 192
16  CoreFoundation                  0x2f68f5c8 _CFStreamSignalEvent + 324
17  CFNetwork                       0x2f2f277a  
CoreReadStreamCFStreamSupport::coreStreamReadEvent(__CoreReadStream*, unsigned long) +   
70
18  CFNetwork                       0x2f2f2726    
CoreReadStreamClient::coreStreamEventsAvailable(unsigned long) + 34
19  CFNetwork                       0x2f399110 
CoreStreamBase::_callClientNow(CoreStreamClient*) + 40
20  CFNetwork                       0x2f2f24ca  
CoreStreamBase::_streamSetEventAndScheduleDelivery(unsigned long, unsigned char) + 118
21  CFNetwork                       0x2f2f2376 
CoreStreamBase::_streamInterface_SignalEvent(unsigned long, CFStreamError const*) + 30
22  CFNetwork                       0x2f2f2312  
SocketStream::dispatchSignalFromSocketCallbackUnlocked(SocketStreamSignalHolder*) + 50
23  CFNetwork                       0x2f2f1db4 
SocketStream::socketCallback(__CFSocket*, unsigned long, __CFData const*, void const*)   
+ 140
24  CFNetwork                       0x2f2f1cee  
SocketStream::_SocketCallBack_stream(__CFSocket*, unsigned long, __CFData const*, void    
const*, void*) + 54
25  CoreFoundation                  0x2f6cb334 __CFSocketPerformV0 + 576
26  CoreFoundation                  0x2f6c9180 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 12
27  CoreFoundation                  0x2f6c864e __CFRunLoopDoSources0 + 202
28  CoreFoundation                  0x2f6c6e42 __CFRunLoopRun + 618
29  CoreFoundation                  0x2f631c22 CFRunLoopRunSpecific + 518
30  CoreFoundation                  0x2f631a06 CFRunLoopRunInMode + 102
31  GraphicsServices                0x3432527e GSEventRunModal + 134
32  UIKit                           0x31ed5044 UIApplicationMain + 1132
33  Web                             0x000821f6 0x81000 + 4598
34  libdyld.dylib                   0x3a374ab4 start + 0

Thread 1:
0   libsystem_kernel.dylib          0x3a41883c kevent64 + 24
1   libdispatch.dylib               0x3a359210 _dispatch_mgr_invoke + 228
2   libdispatch.dylib               0x3a358f96 _dispatch_mgr_thread$VARIANT$mp + 34

Thread 2:
0   libsystem_kernel.dylib          0x3a42bc7c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x3a491dc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib         0x3a491c80 start_wqthread + 4

Thread 3:
0   libsystem_kernel.dylib          0x3a42bc7c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x3a491dc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib         0x3a491c80 start_wqthread + 4

Thread 4 name:  WebThread
Thread 4 Crashed:
0   CoreFoundation                  0x2f62e894 CFRelease + 1132
1   WebCore                         0x37814010 WebCore::stopSharedTimer() + 28
2   WebCore                         0x37a58150  
WebCore::DeferrableOneShotTimer<WebCore::CachedResource>::fired() + 40
3   WebCore                         0x377863fc  
WebCore::ThreadTimers::sharedTimerFiredInternal() + 132
4   WebCore                         0x3778634e WebCore::timerFired(__CFRunLoopTimer*,  
void*) + 22
5   CoreFoundation                  0x2f6c90dc 
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 12
6   CoreFoundation                  0x2f6c8cf2 __CFRunLoopDoTimer + 778
7   CoreFoundation                  0x2f6c708e __CFRunLoopRun + 1206
8   CoreFoundation                  0x2f631c22 CFRunLoopRunSpecific + 518
9   CoreFoundation                  0x2f631a06 CFRunLoopRunInMode + 102
10  WebCore                         0x37814266 RunWebThread(void*) + 414
11  libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
12  libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
13  libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 5 name:  com.apple.NSURLConnectionLoader
Thread 5:
0   libsystem_kernel.dylib          0x3a418a8c mach_msg_trap + 20
1   libsystem_kernel.dylib          0x3a418888 mach_msg + 44
2   CoreFoundation                  0x2f6c87be __CFRunLoopServiceMachPort + 150
3   CoreFoundation                  0x2f6c6ee4 __CFRunLoopRun + 780
4   CoreFoundation                  0x2f631c22 CFRunLoopRunSpecific + 518
5   CoreFoundation                  0x2f631a06 CFRunLoopRunInMode + 102
6   Foundation                      0x3006c2f2 +[NSURLConnection(Loader) 
_resourceLoadLoop:] + 314
7   Foundation                      0x300e1c82 __NSThread__main__ + 1058
8   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
9   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
10  libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 6:
0   libsystem_kernel.dylib          0x3a418a8c mach_msg_trap + 20
1   libsystem_kernel.dylib          0x3a418888 mach_msg + 44
2   CoreFoundation                  0x2f6c87be __CFRunLoopServiceMachPort + 150
3   CoreFoundation                  0x2f6c6ee4 __CFRunLoopRun + 780
4   CoreFoundation                  0x2f631c22 CFRunLoopRunSpecific + 518
5   CoreFoundation                  0x2f631a06 CFRunLoopRunInMode + 102
6   libAVFAudio.dylib               0x2e6b4584 GenericRunLoopThread::Entry(void*) + 124
7   libAVFAudio.dylib               0x2e6a899c CAPThread::Entry(CAPThread*) + 176
8   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
9   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
10  libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 7:
0   libsystem_kernel.dylib          0x3a42bc7c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x3a491dc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib         0x3a491c80 start_wqthread + 4

Thread 8:
0   libsystem_kernel.dylib          0x3a42bc7c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x3a491dc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib         0x3a491c80 start_wqthread + 4

Thread 9 name:  JavaScriptCore::BlockFree
Thread 9:
0   libsystem_kernel.dylib          0x3a42af38 __psynch_cvwait + 24
1   libsystem_pthread.dylib         0x3a493224 _pthread_cond_wait + 536
2   libsystem_pthread.dylib         0x3a494040 pthread_cond_timedwait + 40
3   JavaScriptCore                  0x30656eb0  
WTF::ThreadCondition::timedWait(WTF::Mutex&, double) + 104
4   JavaScriptCore                  0x30656cdc   
JSC::BlockAllocator::blockFreeingThreadMain() + 88
5   JavaScriptCore                  0x306543a0 WTF::wtfThreadEntryPoint(void*) + 12
6   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
7   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
8   libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 10 name:  JavaScriptCore::Marking
Thread 10:
0   libsystem_kernel.dylib          0x3a42af38 __psynch_cvwait + 24
1   libsystem_pthread.dylib         0x3a493224 _pthread_cond_wait + 536
2   libsystem_pthread.dylib         0x3a494000 pthread_cond_wait + 36
3   JavaScriptCore                  0x307f2236 JSC::GCThread::waitForNextPhase() + 74
4   JavaScriptCore                  0x307f2290 JSC::GCThread::gcThreadMain() + 48
5   JavaScriptCore                  0x306543a0 WTF::wtfThreadEntryPoint(void*) + 12
6   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
7   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
8   libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 11 name:  WebCore: CFNetwork Loader
Thread 11:
0   libsystem_kernel.dylib          0x3a418a8c mach_msg_trap + 20
1   libsystem_kernel.dylib          0x3a418888 mach_msg + 44
2   CoreFoundation                  0x2f6c87be __CFRunLoopServiceMachPort + 150
3   CoreFoundation                  0x2f6c6ee4 __CFRunLoopRun + 780
4   CoreFoundation                  0x2f631c22 CFRunLoopRunSpecific + 518
5   CoreFoundation                  0x2f631a06 CFRunLoopRunInMode + 102
6   WebCore                         0x3785cd5a WebCore::runLoaderThread(void*) + 250
7   JavaScriptCore                  0x306543a0 WTF::wtfThreadEntryPoint(void*) + 12
8   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
9   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
10  libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 12 name:  com.apple.CFSocket.private
Thread 12:
0   libsystem_kernel.dylib          0x3a42b440 select$DARWIN_EXTSN + 20
1   CoreFoundation                  0x2f6cc680 __CFSocketManager + 480
2   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
3   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
4   libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 13:
0   libsystem_kernel.dylib          0x3a42bc7c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x3a491dc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib         0x3a491c80 start_wqthread + 4

Thread 14:
0   libsystem_kernel.dylib          0x3a42bc7c __workq_kernreturn + 8
1   libsystem_pthread.dylib         0x3a491dc6 _pthread_wqthread + 306
2   libsystem_pthread.dylib         0x3a491c80 start_wqthread + 4

Thread 15 name:  WebCore: LocalStorage
Thread 15:
0   libsystem_kernel.dylib          0x3a42af38 __psynch_cvwait + 24
1   libsystem_pthread.dylib         0x3a493224 _pthread_cond_wait + 536
2   libsystem_pthread.dylib         0x3a494000 pthread_cond_wait + 36
3   JavaScriptCore                  0x30656e82 
WTF::ThreadCondition::timedWait(WTF::Mutex&, double) + 58
4   WebCore                         0x379473a8 WTF::PassOwnPtr<WTF::Function<void ()> >   
WTF::MessageQueue<WTF::Function<void ()> >::waitForMessageFilteredWithTimeout<bool  
(WTF::Function<void ()>*)>(WTF::MessageQueueWaitResult&, bool (&)(WTF::Function<void   
()>*), double) + 104
5   WebCore                         0x3794732e   
WebCore::StorageThread::threadEntryPoint() + 162
6   JavaScriptCore                  0x306543a0 WTF::wtfThreadEntryPoint(void*) + 12
7   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138
8   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
9   libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 16 name:  WebCore: LocalStorage
Thread 16:
0   libsystem_kernel.dylib          0x3a42af38 __psynch_cvwait + 24
1   libsystem_pthread.dylib         0x3a493224 _pthread_cond_wait + 536
2   libsystem_pthread.dylib         0x3a494000 pthread_cond_wait + 36
3   JavaScriptCore                  0x30656e82  
WTF::ThreadCondition::timedWait(WTF::Mutex&, double) + 58
4   WebCore                         0x379473a8 WTF::PassOwnPtr<WTF::Function<void ()> >    
WTF::MessageQueue<WTF::Function<void ()> >::waitForMessageFilteredWithTimeout<bool  
(WTF::Function<void ()>*)>(WTF::MessageQueueWaitResult&, bool (&)(WTF::Function<void  
()>*), double) + 104
5   WebCore                         0x3794732e  
WebCore::StorageThread::threadEntryPoint() + 162
6   JavaScriptCore                  0x306543a0 WTF::wtfThreadEntryPoint(void*) + 12
7   libsystem_pthread.dylib         0x3a493c1a _pthread_body + 138`enter code here`
8   libsystem_pthread.dylib         0x3a493b8a _pthread_start + 98
9   libsystem_pthread.dylib         0x3a491c8c thread_start + 4

Thread 4 crashed with ARM Thread State (32-bit):
r0: 0x00000000    r1: 0x7e190594      r2: 0x155bc514      r3: 0x00000001
r4: 0x3bfa51ec    r5: 0x0275793c      r6: 0x00000000      r7: 0x028ee074
r8: 0x155bc568    r9: 0x03002c80     r10: 0x028ee128     r11: 0x155bc510
ip: 0x3bee191c    sp: 0x028ee034      lr: 0x37814015      pc: 0x2f62e894
cpsr: 0x60000030

Any insight would be extremely helpful. Thank you!

j08691
  • 204,283
  • 31
  • 260
  • 272
user3203339
  • 261
  • 2
  • 3

2 Answers2

0

From the crash log:

Triggered by Thread:  4

...

Thread 4 name:  WebThread
Thread 4 Crashed:
0   CoreFoundation                  0x2f62e894 CFRelease + 1132
1   WebCore                         0x37814010 WebCore::stopSharedTimer() + 28
2   WebCore                         0x37a58150 WebCore::DeferrableOneShotTimer<WebCore::CachedResource>::fired() + 40

It looks like CFRelease is failing, probably due releasing something that has already been released (although the offset into CFRelease looks strangely high). Regardless this really has to be a bug in WebKit. Have you tried updating to a later version of iOS?

Also I notice in your code sample you're unbinding from "click" but not from "tap". Not sure if this is intentional or not (presumably just a copy paste issue because I also notice you attach "tap" to handleStartClicked but the function you pasted is onStartClicked).

Dave
  • 4,420
  • 1
  • 34
  • 39
0

I had a similar problem with mobile Safari and HammerJS, it was the use of localStorage that caused the random crashes. I am still not sure why it happened, but it worked once we abstracted localstorage elsewhere and used eventemitter with the hammerjs listeners.

Hammer(this.startButton).on('press tap', function(){
    that.emit('handleClickStart', this.sfs);
}

Controller.prototype.__proto__ = EventEmitter2.prototype; 

Controller.prototype.handleClickStart = function(sfs){
    if (!credential) return;

    storageLib.set('credentials', credentials);

    sfs.connect();
};

var storageLib = {
    localStorage: localStorage,
    set: function(key, val) {
        if(val instanceof Object) val = JSON.stringify(val);
        this.localStorage.setItem(key, val);
        return this.isSet(key);
    },
    isSet: function(key){
        var item = this.localStorage.getItem(key);
        if(item) return true;
        else return false;
    }
};
Sinan Guclu
  • 1,075
  • 6
  • 16