Problem
App crashes after several calls to the socket running on the app. Sometimes it crashes after 2-3 requests, but I have seen it take up to 30.
Test case
var info = Ti.API.info;
///=====================
var socket = undefined;
var connectedSockets = [];
function connect()
{
if(socket === undefined || socket.state === Ti.Network.Socket.CLOSED)
{
socket = Titanium.Network.Socket.createTCP({
host:Ti.Platform.address,
port:8080,
listenQueueSize:100,
accepted: accepted,
closed: function(e)
{
info("Closed listener");
},
error: function(e)
{
Ti.API.error("Socket encountered error when listening");
Ti.API.error(" error code '" + e.errorCode + "'");
Ti.API.error(" error description '" + e.error + "'");
}
});
try
{
socket.listen();
info("###Listening on " + socket.host + ":" + socket.port);
socket.accept(acceptedCallbacks);
} catch (e)
{
info('Exception: ' + e);
}
}
}
function accepted(e)
{
var sock = e.inbound;
info('ACCEPTED: ' + sock.host + ':' + sock.port);
Ti.Stream.pump(sock, pumpCallback, 1024, true);
socket.accept(acceptedCallbacks);
}
function pumpCallback(e)
{
var sock = e.source;
if(e.bytesProcessed == -1)
{ // EOF
info("<EOF> - Closing the remote socket!");
removeSocket(sock);
sock.close();
}
else
{
if(e.errorDescription === undefined || e.errorDescription === "")
{
info("DATA: " + e.buffer.toString());
//--
try
{
var s = "Sup world!";
var msg = "HTTP/1.1 200 OK\n";
msg += "Date: Fri, 31 Dec 1999 23:59:59 GMT\n";
msg += "Connection: close\n";
msg += "Content-Type: text/html\n";
msg += "Content-Length: " + s.length + "\n";
msg += "\n";
msg += s;
sock.write(Ti.createBuffer({value: msg}));
sock.close();
} catch (e)
{
info('Exception: ' + e);
}
//--
}
else
{
info("READ ERROR: " + e.errorDescription);
}
}
}
var acceptedCallbacks = {
error : function(e)
{
Ti.API.info(e.error);
Ti.UI.createAlertDialog({
title:"Socket error: " + e.socket.host,
message:e.error
}).show();
}
};
exports.start = function() {
connect();
}
Logs
2012-02-18 13:51:20.345 Kiosk[69478:1be07] -[KrollObject getCFRunLoop]: unrecognized selector sent to instance 0x9d7f790
[ERROR] The application has crashed with an unhandled exception. Stack trace:
0 CoreFoundation 0x030b1052 __exceptionPreprocess + 178
1 libobjc.A.dylib 0x03242d0a objc_exception_throw + 44
2 CoreFoundation 0x030b2ced -[NSObject doesNotRecognizeSelector:] + 253
3 CoreFoundation 0x03017f00 ___forwarding___ + 432
4 CoreFoundation 0x03017ce2 _CF_forwarding_prep_0 + 50
5 Kiosk 0x001c32b8 -[AsyncSocket attachStreamsToRunLoop:error:] + 104
6 Kiosk 0x001c2b8f -[AsyncSocket doAcceptFromSocket:withNewNativeSocket:] + 607
7 Kiosk 0x001cb2b8 -[AsyncSocket doCFSocketCallback:forSocket:withAddress:withData:] + 488
8 Kiosk 0x001c1fd4 MyCFSocketCallback + 196
9 CoreFoundation 0x0301fe44 __CFSocketPerformV0 + 948
10 CoreFoundation 0x0308597f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
11 CoreFoundation 0x02fe8b73 __CFRunLoopDoSources0 + 243
12 CoreFoundation 0x02fe8454 __CFRunLoopRun + 1012
13 CoreFoundation 0x02fe7db4 CFRunLoopRunSpecific + 212
14 CoreFoundation 0x02fe7ccb CFRunLoopRunInMode + 123
15 Foundation 0x0103041f -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 300
16 Kiosk 0x0020bac5 -[TiNetworkSocketTCPProxy socketRunLoop] + 325
17 Kiosk 0x0020c27b -[TiNetworkSocketTCPProxy startListeningSocket] + 699
18 Foundation 0x00ffc4e6 -[NSThread main] + 76
19 Foundation 0x00ffc457 __NSThread__main__ + 1258
20 libsystem_c.dylib 0x931e9ed9 _pthread_start + 335
21 libsystem_c.dylib 0x931ed6de thread_start + 34
2012-02-18 13:51:20.349 Kiosk[69478:1be07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[KrollObject getCFRunLoop]: unrecognized selector sent to instance 0x9d7f790'
*** First throw call stack:
(0x30b1052 0x3242d0a 0x30b2ced 0x3017f00 0x3017ce2 0x1c32b8 0x1c2b8f 0x1cb2b8 0x1c1fd4 0x301fe44 0x308597f 0x2fe8b73 0x2fe8454 0x2fe7db4 0x2fe7ccb 0x103041f 0x20bac5 0x20c27b 0xffc4e6 0xffc457 0x931e9ed9 0x931ed6de)
terminate called throwing an exception
Unfortunately, with the given test, app.js needed fixing (removing the exports.start) and we're not finding any prematurely-released sockets. Instead, they're being held about. Can you refine the test case and ensure it works?
just run this code in an iOS app, and paste the IP address found in the console into a browser and refresh the browser a few times. Also, while normally I have found the above code will crash after 2-3 requests, it can at times take about 10-20
Still can't recreate this and the test JS has a bug: {quote} line = 57; message = "Can't find variable: removeSocket"; {quote} In other words, the removeSocket function referenced isn't in the test suite. Can you recreate the crash using the latest build? It might have already been fixed in the last two weeks since the most recently reported build it was tested.
Please reopen when reproduced on most recent builds.
Sorry, that method was no longer used...
And I just tried with the latest build - Titanium SDK version: 2.0.0 (03/08/12 12:47 4bc31b0) The issue still exists
This sample code includes information only about one endpoint of the socket system (the listener). To resolve and test the issue we will also need information about the data being pushed over the wire and a method to do so.
I am just visiting the ip address / port from a browser... No data is being posted to the app beyond browser headers
OK, thanks for the information. That's what I'll use for testing.
Note that this bug only appears on non-local (no loopback, no simulator) testing. This appears to be a timing issue related to bad runloop management, which can be resolved by switching sockets to another mechanism (GCD!).
TESTING
---- This ticket should be tested with the code in the comment above, by doing the following:The test *MUST* be run on a device, which is connected to the same LAN (wifi access point) as the machine(s) which will connect to it.
Using a browser (any) on the testing machine(s), connect to the endpoint the device is listening on (IP address/port are printed in the console log)
*PASS 1*: A plain HTML page with "Sup world!" on it.
NOW: Slam the reload button in the browser as hard and fast as you can, repeatedly, for as long as you want.
*PASS 2*: The page continuously loads, the listening socket continues to listen, and there are no crashes on the device.
Testing of this ticket should also run the drillbit Socket.TCP test.Resolved by PR 1703
Thanks guys!
Anvil test case added. PR link: https://github.com/appcelerator/titanium_mobile/pull/5011