If you are using Internet Explorer, please remove blackberry.com from your compatibility view settings.

Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
malcolm
Posts: 41
Registered: ‎08-01-2008
My Device: Not Specified

Terminating threads blocked trying to write to closed IO channels?

[ Edited ]

 

Further to my previous thread of the day, I can now receive notifications that Wi-Fi has been shut down. What I would like to do is cause any threads blocked on trying to send data on a JavaOutputStream (which points to the Wi-Fi connection) to terminate cleanly as soon as possible. I have tried calling close() on the JavaOutputStream but I find that if another thread has already tried to call some method on this class then it will not return from this method, except after a minute or so when the connection finally times out. I'd like to avoid this delay if possible.

 

Here is where the writing threads are generally stuck I find (and they stay stuck even after calling close):

 

 

Object.wait() : 479
Protocol.addToOutputBuffer( byte[], int, int ) : 747
SimulTcpOutputStream?.write( byte[], int, int ) : 91
JavaOutStream?.flush( ) : 46
JavaOutStream?.writeBytes( byte[], int, int ) : 32
//My methods below here...

 

 It appears the thread has called wait on some mutex, but as far as I can see without the source there is no way I can acquire this mutex and do notifyAll()... An ideal solution would be to make the writing thread throw an exception which passes all the way out to my code and can be handled there. Is there any way to get around this problem?

 

 

Edit: I've just found the Thread.interrupt method. This sounds like exactly what I need, but it doesn't seem to cause the thread in question to throw an InterruptedException, or do anything really. Is this method supposed to work even when constructing a thread with "new thread(<Runnable object here>);" ?


 

Message Edited by malcolm on 09-10-2008 11:13 AM
Please use plain text.
Developer
marchywka
Posts: 1,415
Registered: ‎07-30-2008
My Device: Not Specified

Re: Terminating threads blocked trying to write to closed IO channels?

From the RIM documentation, it looks like interrupt() in CLDC doesn't have to clean up IO and apparently it may not even get

a stuck thread to throw. Thread.stop() apparently is completley gone and I'm not sure if there is any other way

to force a ThreadDeathError ( since this isn't listed in the classes, it probably no longer exists as there is no way to create one).

I guess the option is to find someway to get the IO thing to throw an IO exception other than close().

 

 

Please use plain text.
Developer
richard_puckett
Posts: 191
Registered: ‎04-03-2008
My Device: Bold 9700

Re: Terminating threads blocked trying to write to closed IO channels?

[ Edited ]

  So, uh, here's how I do it.  My whole networking bit is implemented as a multithreaded work queue, but I'll try to post the more relevant parts from it.

 

  Ultimately, your networking probably isn't in an Object.wait, it's blocking on IO.  What you want to do is call "close" on your HTTPConnection (which means you need to squirrel away a reference to that object somewhere).  Here's what some of my stuff looks like:

 

public class HTTPRequestWorkUnit implements Cancelable, Runnable { private HttpConnection httpConnection = null; public void cancel() { if (httpConnection != null) { try { httpConnection.close(); } catch (IOException ignore) { }

finally { 

cancelRequest();

} } } ... }

 

  The HTTPRequestWorkUnit is what gets added to my work queue and Cancelable is an interface which only contains the "cancel" method - I use that to determine if work queue runnables can be canceled.  The "run" method of HTTPRequestWorkUnit does all the heavy lifting.  "cancelRequest" cleans up any pending HTTPConnections and InputStreams and fires a notification to listeners.  Here's part of "run":

	

public synchronized void run() { byte[] data = null; while (shouldRequest()) { currentRequest++; try { httpConnection = (HttpConnection) Connector.open(url); int responseCode = httpConnection.getResponseCode();

...

  So if I want to cancel a networking request I call "cancel" on this Runnable and then also call "interrupt" on my PoolWorker thread (which is what pulls Runnables from my work queue and starts them).  There's more to all this, but hopefully it's somewhat clear as to what's going on.

 

  So to recap: The networking thread can be canceled by forcing a close of the HTTPConnection.  Doing this will throw a net.rim.device.api.io.ConnectionClosedException, but I don't really care about that when I'm canceling the connection anyway, so I ignore it.

 

  FWIW, I also use a volatile flag to signal when it should cancel since it follows redirects and might not be blocking on network IO when the cancel request comes in.

Message Edited by richard_puckett on 09-19-2008 10:35 PM
Please use plain text.
Developer
marchywka
Posts: 1,415
Registered: ‎07-30-2008
My Device: Not Specified

Re: Terminating threads blocked trying to write to closed IO channels?

I think the OP claimed he closed the relevant stream, not sure about any connection. 

The IO has to have some implementation and any particular implementation could have quirks or bugs.

Presumably await() could be  waiting on a notify() from a thread that talks to the hardware or something similar.

Hacking and cracking is not always a waste of time :smileyhappy: 

 

Certainly closing all the streams and connections is the first line of defense but take a look at the comments

on Thread.interrupt() for CLDC. Thread.stop() was deprecated a long time ago and appears to be completely gone now.

 

If you get stuck here:

synchronized (foo) {

 

because someone else already has foo what do you do? I'm not sure if Thread.interrupt() works above or if it works uniformly.

 

I don't think anyone has come up with a uniform solution for IO and IIRC there are even a lot of question about what to do with lock

when threads get clobbered, which was why stop() was deprecated.

 

 http://java.sun.com/j2se/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

 

Besides system.exit() I'm not sure what the options are here.

 

 

 

 

 

Please use plain text.