Interrupting blocking IO calls | Telit Cinterion IoT Developer Community
March 24, 2015 - 6:08pm, 7313 views
we're in the process of implementing a TCP socket connection from a EHS6 to a cloud server. The vast majority of the code is done and is now is the maturing phase.
1. I've noticed that the Connector.open() accepts a third parameter indicating timeouts, which is only a hint. After testing that parameter and connecting to a bogus address, the open() method never timed-out and is blocking any other operations.
Is it possible by any call to unblock this .open() call (there is no object to call .close on)?
2. I've noticed that after having a connection via Connector.open(), you can open an outputstream. This outputstream can be used to write bytes to the remote side. However, this is also a blocking call, which can block indefinitly at any point in time, since a GSM network is hostile per definition.
Is it possible by any call to unblock this .write() call (by SocketConnection.close()?) or is there a write call with timeout?
3. I've noticed that after having a connection via Connector.open(), you can open an inputstream. This inputstream can be used to read bytes to the remote side. However, this is also a blocking call, which can block indefinitly at any point in time, since a GSM network is hostile per definition.
Is it possible by any call to unblock this .read() call (by SocketConnection.close()?) or is there a read call with timeout?
What puzzles me is that a Java ME implementation was used in a hostile environment with no certainties whatsoever without giving a programmer the means to do something about it.
Could you advise me how such things are to be tackled?
I have run in similar problems. I had implemented java Watchdog so that it resets the module if there is a long timeout when sending data. But like you said it would be nice to set timeout or call unblock somehow.
Unfortunately, watchdogging the module is not an option. We're creating an consumer alarming device, where the alarm-message ***** to be delivered to a cloud server, resetting the module is a no-go. It should timeout, after which we try an alternative alarming path, such as SMS.
What about that communication with the server would be a new thread, and inside main thread you check for how long is running and if it's to long you send SMS?
You mean to let the thread simply linger around. I've found a similar approach on the web here but as a developer, that's not something I'm custom to. As this is an embedded environment, I'd like to clean up as I'm used to and not deliberately keep orphaned threads lingering around. I'm not sure if a GC would ever clean that up.
Ps. it's not only an alarm-message, there are numerous messages that could suffer the same fate. I'm wondering how Gemalto solved this in their SensorLogic solution. They must have run into the same issues.
1. I've checked that it really takes some time to get Exception which connecting to the address that does not exist. But the exception should come and the connection should not be blocked forever.
This parameter only means that the application wants to get timeout exceptions but does not guarantee when they will come.
2. Have you tested that writing to the remote host can be blocked on the write method? This should not happen.
3. Read method is indeed a blocking one. It blocks until there are data to be read. To avoid this you can use DataInputStream and test if there is data available for reading with available() method.
This behaviour comes from the nature of TCP network. If you already have the connection established and you want to keep it open for a long time there is also a possibility that it will be broken for some reason and you will wait for a long time to get the exception because of TCP timeouts. So in such case it might be a good idea to develop some keep-alive mechanism as part of your communication protocol you are using on top of the sockets.
If delays in communicating the alarm event is critical in your application maybe the best solution would be to implement the timer and try to use SMS in case the communication is not established. In fact in case of this communication channel there is also no guarantee that the message is delivered by the network.
Also maybe the UDP would be worth consideration or testing with some confirmations from the other side.
No matter what I set timeout= in SocketConnection parameters, it took about 160 seconds (logged down start and end time) before timeout occured, the 160 seconds was consistent no matter what value was put in.
Maybe the timeout parameter is useless, the other place is to look at AT^SCFG see if it offers any clue.
After communication is established, as mentioned in one a the comments earlier, it is better to use available() to check before doing a read(), as read() blocks, you roll out your own timeout using while loop, available(), start time variable. So you break the loop if current time - start time > your timeout
The timeout parameter passed to Connector.open() method specifies the Java network idle timeout, which is the number of seconds to wait before the network connection is terminated automatically after having closed the last socket on this connection.
We ran into similar issues, and here is how I resolved(kinda) them:
1. Connection timeout to 30 secs: Since the API doesn't let you set this, I've written a class that does the Connector.Open() call in a thread, which notifies the main thread once connection is done.
So, the chronology goes:
A- The main thread starts this connection by spawning the thread.
B- The main threads waits on the notify object for 30 seconds.
C- Then one of the followin occurs: Connection is done and object is notified -OR- no connection is done and the wait ***** out. If it ***** out, you make sure to perform an interrupt/cleanup of the other thread.
For an async read() operation, I've just written a loop that checks available() repetitively with Thread.sleep(1) until timeout is reached.
Hope this helps.
I've observed the very same issue happening randomly in the field (with Connector.open() getting stuck for ~1h and more). Unfortunately I am not able to reproduce it in lab environment (yet).
Is there anything new known about this issue? Is there any official way to unblock a thread stuck in Connector.open() call? I already run it in a background thread, which I can simply toss away, but I'm afraid about running out of resources (is there any gurantee that the thread will ever unblock?).
There was a problem with connection attempt while no network was available but it's already solved. It can take a long time to detect a broken socket that is already open for reading and writing - and here the most reliable way to close it fast is to develop a custom timer. In case of opening issue that you described it's hard to say what was the reason of it - a wireless network issue, server or backbone. I think that you should try to switch to new firmware. And a timeout might still be a good way as it can always happen that the pending connection will be broken.