Experimental Physics and Industrial Control System
I recently ported JCA/CAJ to android and came across the fact that
BroadcastConnector does not bind the underlying DatagramSocket
to a local address.
According to the java.nio.channels.DatagramChannel docs a channel
is open()ed and then the underlying socket can be bound. Under android
it apparently must be. openjdk is more forgiving and binds the socket
automatically. However, there might be a problem:
For openjdk I came across the following source code
http://cr.openjdk.java.net/~dxu/8000404/webrev/src/share/classes/sun/nio/ch/DatagramChannelImpl.java.html
which happens to match the lines in your stack trace. In this class (I
have no
other reason to believe it is the same implementation you are using than
two matching line numbers) the socket is bound to a local address
automatically
(if the user has not done so already).
At first glance there seems to be a race condition which could explain what
you experience:
receive(ByteBuffer dst) [starting at line 317] contains the following code:
synchronized( readLock ) {
...
if ( localAddress() == null ) {
bind(null);
}
. ...
}
and bind(SocketAddress local) [starting at line 654] is coded:
synchronized( readLock ) {
synchronized ( writeLock ) {
if ( localAddress != null ) {
throw new AlreadyBoundException();
}
// do actual binding here
localAddress = xxx;
}
}
However, in send(ByteBuffer src, SocketAddress target) [starting at line
413] we find
synchronized ( writeLock ) {
...
if ( localAddress == null ) {
localAddress = Net.localAddress( fd );
}
}
Hence, it could occur that thread A takes the read lock, tests
localAddress and
then proceeds to bind. It finds the writeLock held by thread B which -
in the middle
of 'send' - sets 'localAddress'. When thread A resumes and obtains
'writeLock'
then it finds 'localAddress' non-null and throws the exception.
I don't know how likely this is (do you see this often?) - there might
be other scenarios
or you might not even use the implementation I looked at (I didn't spend
more than 1h
on this analysis).
In any case it is IMHO worthwhile to fix CAJ so that it binds datagram
channels
at creation time:
--- a/src/com/cosylab/epics/caj/impl/BroadcastConnector.java Fri Nov 08
11:26:19 2013 -0800
+++ b/src/com/cosylab/epics/caj/impl/BroadcastConnector.java Fri Nov 08
11:29:22 2013 -0800
@@ -58,6 +58,9 @@
// use non-blocking channel (no need for soTimeout)
socket.configureBlocking(false);
+
+ // bind to any local port
+ socket.socket().bind( null );
// set SO_BROADCAST
socket.socket().setBroadcast(true);
HTH
-- Till
On 12/04/2013 06:48 PM, Kasemir, Kay wrote:
Hello:
Does anybody else see these messages from CAJ, the pure java channel access client?
Thanks,
Kay
2013-12-04 14:44:27.667 SEVERE [Thread 25] com.cosylab.epics.caj.impl.reactor.Reactor (processInternal) -
java.nio.channels.AlreadyBoundException
at sun.nio.ch.DatagramChannelImpl.bind(DatagramChannelImpl.java:661)
at sun.nio.ch.DatagramChannelImpl.receive(DatagramChannelImpl.java:327)
at com.cosylab.epics.caj.impl.BroadcastTransport.processRead(BroadcastTransport.java:178)
at com.cosylab.epics.caj.impl.BroadcastTransport.handleEvent(BroadcastTransport.java:155)
at com.cosylab.epics.caj.impl.reactor.lf.LeaderFollowersHandler.handleEvent(LeaderFollowersHandler.java:77)
at com.cosylab.epics.caj.impl.reactor.Reactor.processInternal(Reactor.java:400)
at com.cosylab.epics.caj.impl.reactor.Reactor.process(Reactor.java:284)
at com.cosylab.epics.caj.CAJContext$2.run(CAJContext.java:708)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:722)
- References:
- CAJ "AlreadyBoundException" Kasemir, Kay
- Navigate by Date:
- Prev:
Re: CAJ "AlreadyBoundException" Mark Rivers
- Next:
Re: which time/timestamp format to use for an EPICS facility? Benoit
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
<2013>
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
- Navigate by Thread:
- Prev:
Re: CAJ "AlreadyBoundException" Mark Rivers
- Next:
StreamDevice "No reply from device" messages John Dobbins
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
<2013>
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024