[jboss-dev] Remoting behavior on error (Re: Possible blocker with jboss-cl 2.2.0.Alpha1)

Ron Sigal ron.sigal at jboss.com
Fri Feb 19 12:15:46 EST 2010


JBREM-1188 "Socket transport doesn't set "timeout" to default value".

Mia faccia e un pomodoro!  [My face is a tomato!]

Thanks, Jaikiran!

-Ron

Jaikiran Pai wrote:
> Bug, bug, bug ;)
>
> There's some Java initialization trick going on with that piece of 
> code (only relevant code has been pasted below):
>
> public class SocketClientInvoker extends MicroSocketClientInvoker
> {
>
>   /**
>    * Default value for socket timeout is 30 minutes.
>    */
>   public static final int SO_TIMEOUT_DEFAULT = 1800000;
>
>   protected int timeout = SO_TIMEOUT_DEFAULT;
>   ...
>
>   public SocketClientInvoker(InvokerLocator locator)
>   {
>      this(locator, null);
>   }
>
>   public SocketClientInvoker(InvokerLocator locator, Map configuration)
>   {
>      super(locator, configuration);
>      configureParameters();
>   }
>
>   protected ServerAddress createServerAddress(InetAddress addr, int port)
>   {
>      return new ServerAddress(addr.getHostAddress(), port, 
> enableTcpNoDelay, timeout, maxPoolSize);
>   }
> ...
> }
>
>
> public class MicroSocketClientInvoker ...
> {
>
>   public MicroSocketClientInvoker(InvokerLocator locator, Map 
> configuration)
>   {
>      ...
>
>      try
>      {
>         setup();
>      }
>      ...
>
>      log.debug(this + " constructed");
>   }
>
>   protected void setup() throws Exception
>   {
>      ...
>         address = createServerAddress(addr, port);
>      }
> ...
> }
>
> 1) SocketClientInvoker extends MicroSocketClientInvoker
> 2) When someone constructs SocketClientInvoker through it's 
> constructor, JVM first constructs MicroSocketClientInvoker.
> 3) This includes MicroSocketClientInvoker's object field 
> initialization and then the code execution in 
> MicroSocketClientInvoker's constructor.
> 4) MicroSocketClientInvoker's constructor invokes setup() on itself 
> which then invokes the (overridden) createServerAddress() on 
> SocketClientInvoker
> 5) Note that, at this point the object field initialization of 
> SocketClientInvoker has *not* yet been done. So the
>
> protected int timeout = SO_TIMEOUT_DEFAULT;
>
> in SocketClientInvoker hasn't yet been executed. Effectively, when 
> SocketClientInvoker.createServerAddress() is invoked, the timeout 
> value is 0. As a result, SocketClientInvoker.createServerAddress() 
> ends up creating a ServerAddress with timeout = 0 (infinite timeout).
> (Rest of the flow is irrelevant, but let's just outline it here for 
> the sake of completeness)
> 6) After completion of SocketClientInvoker.createServerAddress() 
> method invoked in step#4, the MicroSocketClientInvoker.setup too 
> completes and ultimately the code execution in the 
> MicroSocketClientInvoker's constructor too is completed.
> 7) After step#6, the object field initialization of 
> SocketClientInvoker starts and it's at this point where the timeout 
> field value gets set to 1800000, but by now it's too late.
>
> And here are the logs (only a part of the entire log file) from 
> remoting which prove that the timeout is being set to 0:
>
> 2010-02-19 16:32:29,104 DEBUG [org.jboss.remoting.Client] 
> Client[16278782:3j001-51zxod-g5uvg99p-1-g5uvg99q-2].connect(null)
> 2010-02-19 16:32:29,104 TRACE [org.jboss.remoting.Client] 
> Client[16278782:3j001-51zxod-g5uvg99p-1-g5uvg99q-2]: metadata = null
> 2010-02-19 16:32:29,172 DEBUG 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] 
> constructed
> 2010-02-19 16:32:29,172 DEBUG 
> [org.jboss.remoting.MicroRemoteClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] 
> connecting
> 2010-02-19 16:32:29,173 DEBUG 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> Creating semaphore with size 50
> 2010-02-19 16:32:29,173 TRACE 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] added 
> new pool ([]) as ServerAddress[127.0.0.1:3873, NO enableTcpNoDelay 
> timeout 0 ms, maxPoolSize=50]
> ....
> 2010-02-19 16:32:29,185 TRACE 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] 
> retryCount: 0
> 2010-02-19 16:32:29,185 TRACE 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] 
> obtained semaphore: 49
> 2010-02-19 16:32:29,185 TRACE 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] 
> creating socket
> 2010-02-19 16:32:29,186 TRACE 
> [org.jboss.remoting.transport.socket.MicroSocketClientInvoker] 
> SocketClientInvoker[879860, socket://localhost.localdomain:3873] 
> created socket: Socket[addr=/127.0.0.1,port=3873,localport=39135]
> 2010-02-19 16:32:29,187 TRACE 
> [org.jboss.remoting.transport.socket.SocketWrapper] constructing 
> org.jboss.remoting.transport.socket.ClientSocketWrapper instance for 
> Socket[addr=/127.0.0.1,port=3873,localport=39135], using timeout 0
> 2010-02-19 16:32:29,187 TRACE 
> [org.jboss.remoting.transport.socket.SocketWrapper] 
> ClientSocketWrapper[Socket[addr=/127.0.0.1,port=3873,localport=39135].6c5482] 
> setting timeout to 0
> ...
>
> regards,
> -Jaikiran
>
> Ron Sigal wrote:
>> Uh, maybe it's 30 minutes in metric.  :)
>>
>> Actually, we fooled you.  The actual client invoker is 
>> org.jboss.remoting.transport.socket.SocketClientInvoker, which 
>> overrides createServerAddress():
>>
>>    protected ServerAddress createServerAddress()
>>    {
>>       return new ServerAddress(addr.getHostAddress(), port, 
>> enableTcpNoDelay, timeout, maxPoolSize);
>>    }
>>
>> "Once upon upon, in a disney far away", Tom Elrod got a request to 
>> make Remoting suitable for micro devices without timeouts, and he 
>> broke out MicroSocketClientInvoker from the original 
>> SocketClientInvoker.  It never went anywhere, since the requester 
>> soon disappeared, as usual.
>>
>> -Ron
>>
>> ===========================
>> /*Snore Wife and Some Several Dwarts*
>>
>> Once upon upon in a dizney far away - say three hundred year agoal if 
>> you like-there lived in a sneaky forest some several dwarts or 
>> cretins; all named - Sleezy, Grumpty, Sneeky, Dog, Smirkey, Alice? 
>> Derick - and Wimpey. Anyway they all dug about in a diamond mind, 
>> which was rich beyond compere. Every day when they came hulme from 
>> wirk, they would sing a song - just like ordinary wirkers - the song 
>> went something like - 'Yo, ho! Yo, ho! it's off to wirk we go!' - 
>> which is silly really considerable they were comeing hulme. (Perhaps 
>> ther was slight housework to be do.)
>> One day howitzer they (Dwarts) arrived home, at aprodestant six 
>> o'cloth, and who? - who do they find? - but only Snore Wife, asleep 
>> in Grumpty's bed. He didn't seem to mine. 'Sambody's been feeding my 
>> porrage!' screams Wimpey, who was wearing a light blue pullover. 
>> Meanwife in a grand Carstle, not so a mile away, a womand is looging 
>> in her daily mirror shouting, 'Mirror mirror on the wall, whom is de 
>> fairy in the land.' which doesn't even rhyme. 'Cassandle!' answers 
>> the mirror. 'Chirsh O'Malley' studders the womand who appears to be a 
>> Queen or a witch or an acorn.
>>
>> -/John Lennon, /A Spaniard in the Works
>>
>> /
>> Jaikiran Pai wrote:
>>> The testcase has been hung since more than 3 days, now :) So looks 
>>> like that default client timeout of 30 minutes isn't being honoured. 
>>> By the way, EJB3 uses its own config file for remoting 
>>> JBOSS_HOME/server/< 
>>> servername>/deploy/ejb3-connectors-jboss-beans.xml. But that's 
>>> irrelevant since the defaults should apply to any remoting config 
>>> irrespective of which file it's configured in.
>>>
>>> So I looked at this in a bit more detail and it now appears to be a 
>>> bug in JBoss Remoting. Here's what's happening:
>>>
>>> - A EJB3 client interceptor 
>>> (org.jboss.aspects.remoting.InvokeRemoteInterceptor) responsible for 
>>> invoking the remote EJB container does a remoting call:
>>>
>>>     InvokerLocator locator = 
>>> (InvokerLocator)invocation.getMetaData(REMOTING, INVOKER_LOCATOR);
>>>     ...
>>>     Client client = new Client(locator, subsystem);
>>>          try
>>>      {
>>>         client.connect();
>>>     ...
>>>         client.invoke(invocation, null);
>>>
>>> - Remoting internally creates a 
>>> org.jboss.remoting.transport.socket.MicroSocketClientInvoker which 
>>> creates a ServerAddress:
>>>
>>> protected ServerAddress createServerAddress(InetAddress addr, int port)
>>>   {
>>>      return new ServerAddress(addr.getHostAddress(), port, 
>>> enableTcpNoDelay, -1, maxPoolSize);
>>>   }
>>>
>>> Notice the hardcoded -1 being passed to the ServerAddress. That's 
>>> the "timeout". The ServerAddress internally ignores negative timeout 
>>> values and sets the timeout to 0 (resulting in infinite timeout).
>>>
>>> - The MicroSocketClientInvoker then ultimately ends up creating a 
>>> client socket with timeout = 0.
>>>
>>> - So when the server side remoting thread crashes (for any unrelated 
>>> reason - like the classloading issue), the client ends up with this 
>>> infinite block.
>>>
>>> The issues i see here:
>>>
>>> 1) I don't see a way, how i can pass a timeout for the client 
>>> socket. Contrary to the comments in remoting-jboss-beans.xml,  based 
>>> on what i see in the code, it's only the server side timeout which 
>>> has a corresponding param. Did i miss something?
>>>
>>> 2) Even if there was some way of passing the client socket timeout, 
>>> currently the ServerAddress creation through 
>>> MicroSocketClientInvoker hardcodes the timeout to -1.
>>>
>>> regards,
>>> -Jaikiran  Adrian Brock wrote:
>>>> On Tue, 2010-02-16 at 18:14 +0530, Jaikiran Pai wrote:
>>>>> Ron Sigal wrote:
>>>>>> Yeah, Carlo also pointed out that NCDFE is a java.lang.Error, 
>>>>>> which, as you note, is not caught.  I agree that if ServerThread 
>>>>>> is going to terminate due to an error, then it should certainly 
>>>>>> close its socket, so that's a bug (JBREM-1183 "ServerThread 
>>>>>> should catch java.lang.Error").  But I have mixed feelings about 
>>>>>> terminating ServerThread in this case.  Unlike, IOException, 
>>>>>> SocketException, etc., the NoClassDefFoundError doesn't suggest 
>>>>>> that the socket is no longer usable.  Maybe a better solution 
>>>>>> (along with fixing the classloader problem, of course) is to use 
>>>>>> a positive timeout on the client side.
>>>>> I think some (sensible) default timeout needs to be added so that 
>>>>> the client does not end up hung. Is this something that can be 
>>>>> added to some *-jboss-beans.xml in the AS?
>>>>>
>>>>
>>>> It already exists, but whether 30 minutes is a "sensible" default
>>>> is a different issue. ;-)
>>>>
>>>> See remoting-jboss-beans.xml
>>>>
>>>>                         <!-- Socket read timeout.  Defaults to 
>>>> 60000 ms (1 minute)
>>>> -->
>>>>             <!-- on the server, 1800000 ms (30 minutes) on the client.
>>>> -->
>>>>             <!--entry><key>timeout</key> 
>>>> <value>120000</value></entry-->
>>>>
>>>>
>>>
>



More information about the jboss-development mailing list