flash.net.Socket Causes IOS App crash with SDK15
Copy link to clipboard
Copied
We have an IOS app deployed in the app store running on Air SDK 4.0. The app has no problems running on IOS8 devices. Our app uses flash.net.socket to communicate with a server.
We are testing a new update that we want to deploy to the app store and discovered a crashing bug with the flash.net.socket class under a certain circumstance.
Basically, if you loose Wifi, the device usually takes a few seconds to 10 seconds to switch to cellular, or discover it has neither wifi or cellular.
It so happens that if you open a flash.net.socket and connect to a server while the device is in this in-between state where it hasn't detected there is no wifi or network, the air app will just crash with no warning. Another thing about this crash is that it only happens with a release (adhoc or appstore) build but NOT with a debug build.
To reproduce is very straightforward:
1. create a new socket : skt=new Socket();
2. add some event listeners...
3. issue a skt.connect(httpServer,httpPort); to connect the server *immediately* after loosing the wifi connection, but before the wifi icon in the status bar has changed.
4. the connect function will return, then after 1-2 seconds, the app will crash. none of the event handlers, including IOErrorEvent will fire before the crash.
If you wait for the device to switch to cellular or discover it has no network interface(network icons in status bar change), then try to skt.connect(), there is no crash and the event handlers fire.
We have also tried the beta SDK 15 on adobe labs, but it has the same bug. Reverting back to SDK 4.0, there is no crash, and the IOErrorEvent will fire as expected.
Were basically stuck at this point.
Thanks,
-Kelly
Copy link to clipboard
Copied
Thanks for reporting the issue.
I have followed the same steps to reproduce it but not able to find crash. App is working fine using latest SDK.
please provide a sample app for same so that we can easily figure out the cause.
-Pravendra
Copy link to clipboard
Copied
Thanks for the reply Pravendra. We figured out how to get around the crash, and also why you couldn't reproduce it:
Setting a timeout on the socket makes a difference. We use a 10 second timeout, and that causes the crash.
not setting the timeout, or setting it to 20sec or longer, the crash wont happen and the error event will fire.
So, to reproduce:
skt.timeout=10000;
then
skt.connect(host,port);
Then, right after disabling wifi, but before the device reports it, do the socket connection.
We discovered the problem during field testing when the device lost cellular or wifi and didn't have the other available.
Its was hard to reproduce it in the office by switching on off the wifi on the device as that was too slow, but finally found an easy way:
1. connect the device using usb to your OSX box, then in System Preference's->Sharing turn on "internet sharing".
2. connect the device's wifi to your OSX box internet sharing ssid. Use the checkbox to select/unselect Internet sharing to turn on/off.
3. start the connection then quickly uncheck the internet sharing.
I'll send you a message of where to get the test project once I upload it.
Thanks,
Kelly
Copy link to clipboard
Copied
I have added timeout for socket. Still not able to reproduce the crash.
I used the below code:
package
{
import flash.display.Sprite;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.OutputProgressEvent;
import flash.events.ProgressEvent;
import flash.events.SecurityErrorEvent;
import flash.net.Socket;
import flash.text.TextField;
public class SocketTest extends Sprite
{
private var socket:Socket;
private var text1:TextField;
private const host:String = "www.adobe.com";
private const port:int = 80;
public function SocketTest()
{
super();
// support autoOrients
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
socket = new Socket();
trace("a socket is created");
trace(socket);
text1=new TextField();
text1.text ="Click me";
text1.scaleX=5;
text1.scaleY=5;
text1.multiline
addChild(text1);
text1.addEventListener(MouseEvent.CLICK,connect);
socket.addEventListener(Event.CONNECT, onConnected);
socket.addEventListener(IOErrorEvent.IO_ERROR, onSocketIOError);
socket.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, onSocketOutput);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSocketSecurityError);
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}
protected function connect(event:Event):void
{
socket.timeout=10000;
socket.connect(host, port);
text1.text=": Trying to connect :";
}
private function onConnected(e:Event):void
{
text1.text=": Connected Now :";
}
private function socketDataHandler(event:ProgressEvent):void
{
text1.text="SocketData" + event.type;
}
private function onSocketIOError(e:IOErrorEvent):void
{
text1.text="Socket IOError";
}
private function onSocketSecurityError(e:SecurityErrorEvent):void
{
text1.text="Socket SecurityError";
}
private function onSocketOutput(e:OutputProgressEvent):void
{
text1.text="Pending Bytes"+ socket.bytesPending
}
}
}
-Pravendra
Copy link to clipboard
Copied
Hi Pravendra,
Yes, I can get the same crash as your sample - but it has to be a release build. And on several different IOS devices.
You have to be able to to open the socket connection while the device thinks it has a wifi connection but hasn't yet detected one doesn't exist(typically, this is in the 2-5 seconds after wifi is gone), which is a bit tricky to replicate.
To get a realistic test, you need to make sure cellular data is off otherwise another network interface will be available and the crash wont happen.
Then disconnect wifi (preferably by using the procedure in my previous post) and quickly tap your input control to fire off the socket connection.
1. connect the device to your OSX box by enabling "Internet Sharing" in System Preference's->Sharing
2. connect the device's wifi to your OSX box's internet sharing SSID.
3. with internet sharing on and the device connected to the shared wifi: with one hand, uncheck the enable checkbox for internet sharing in the System Preferences->Sharing Panel to deselect Internet sharing to facilitate turning wifi off.
4. Quickly start the socket connection by tapping your screen.
Copy link to clipboard
Copied
I am seeing the same thing, and like Kelly I was able to solve it by doing away with the timeout.
The crash happens whenever it times out after I try to connect to an unreachable network (e.g., if my WiFi is 192.168.1.x and I try to to connect to 192.168.2.x, or if I try to connect to 192.168.1.x while WiFi is off).
If I don’t set the manual timeout, the connection times out naturally with an IOErrorEvent after about 12 seconds.
AIR 14.0 for iOS, iOS 8.1.1 on iPhone 5 and iPad 2.
Copy link to clipboard
Copied
We faced the same issue with App crash on iOS when we set socket timeout. Our work around for iOS is not to affect socket.timeout and to have a Timer that shuts down the socket (socket.close()) after a given delay.
Important advice: make sure your event handlers are strong (i.e. don't set weak to true when you add event handlers), otherwise the socket variable may get removed from memory while handlers are still active, resulting in run-time errors. close the socket then remove handlers explicitly.
Copy link to clipboard
Copied
I had the exact same problem. I added some logging-code using Sockets to my already quite large app, and suddenly it started crashing on iOS!
Built with AIR SDK 17.0.0.144, app tested on iPad 3.
After reading this thread, i noticed i had set the socket.timeout to 5000ms. Removing the assignment to socket.timeout made my app work again, including the new logging code. It's a strange little bug, but at least the workaround is pretty easy!
