Bug has been filed as well through (Review ID: 624057)
When a client crashes or loses its connection while a fragmented call is in
progress, the receiving server thread gets stuck. This wastes a thread on
the server side, and keeps the ORB from shutting down cleanly.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. compile the source provided below
2. In one terminal, run
java com.coremedia.corba.DefragHang
3. copy the IOR that is printed in terminal 1. In a second terminal, run
java com.coremedia.corba.DefragHang <theIORthatWasPrinted> -x 4. In terminal
1, press return (to shutdown the server)
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The output I expect in terminal 1 is:
press any key to shut down...
incoming call...
...call handled
shutting down...
shut down.
ACTUAL -
press any key to shut down...
incoming call...
shutting down...
ERROR MESSAGES/STACK TRACES THAT OCCUR :
for Java 1.5:
"p: default-threadpool; w: 0" daemon prio=5 tid=0x0acc0c60 nid=0x1d08 in
Object.wait() [0x0af0f000..0x0af0fd68]
at java.lang.Object.wait(Native Method)
- waiting on <0x02b39f28> (a
com.sun.corba.se.impl.encoding.BufferQueue)
at java.lang.Object.wait(Object.java:474)
at
com.sun.corba.se.impl.encoding.BufferManagerReadStream.underflow(BufferManag
erReadStream.java:97)
- locked <0x02b39f28> (a com.sun.corba.se.impl.encoding.BufferQueue)
at
com.sun.corba.se.impl.encoding.CDRInputStream_1_1.grow(CDRInputStream_1_1.ja
va:75)
at
com.sun.corba.se.impl.encoding.CDRInputStream_1_0.read_octet_array(CDRInputS
tream_1_0.java:684)
at
com.sun.corba.se.impl.encoding.CDRInputStream.read_octet_array(CDRInputStrea
m.java:177)
at
com.coremedia.corba.DefragHang$MyServant._invoke(DefragHang.java:68)
at
com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatchToSe
rvant(CorbaServerRequestDispatcherImpl.java:637)
at
com.sun.corba.se.impl.protocol.CorbaServerRequestDispatcherImpl.dispatch(Cor
baServerRequestDispatcherImpl.java:189)
at
com.sun.corba.se.impl.protocol.CorbaMessageMediatorImpl.handleRequestRequest
(CorbaMessageMediatorImpl.java:1680)
at
com.sun.corba.se.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaM
essageMediatorImpl.java:1540)
at
com.sun.corba.se.impl.protocol.CorbaMessageMediatorImpl.handleInput(CorbaMes
sageMediatorImpl.java:922)
at
com.sun.corba.se.impl.protocol.giopmsgheaders.RequestMessage_1_2.callback(Re
questMessage_1_2.java:181)
at
com.sun.corba.se.impl.protocol.CorbaMessageMediatorImpl.handleRequest(CorbaM
essageMediatorImpl.java:694)
at
com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl.dispatch(Socke
tOrChannelConnectionImpl.java:451)
at
com.sun.corba.se.impl.transport.SocketOrChannelConnectionImpl.doWork(SocketO
rChannelConnectionImpl.java:1187)
at
com.sun.corba.se.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(Thr
eadPoolImpl.java:417)
for Java 1.4:
"RequestProcessor[0]" daemon prio=5 tid=0x00a66740 nid=0x17d8 in
Object.wait() [2f5f000..2f5fd8c]
at java.lang.Object.wait(Native Method)
- waiting on <0x1007c068> (a
com.sun.corba.se.internal.iiop.BufferQueue)
at java.lang.Object.wait(Object.java:429)
at
com.sun.corba.se.internal.iiop.BufferManagerReadStream.underflow(BufferManag
erReadStream.java:62)
- locked <0x1007c068> (a com.sun.corba.se.internal.iiop.BufferQueue)
at
com.sun.corba.se.internal.iiop.CDRInputStream_1_1.grow(CDRInputStream_1_1.ja
va:73)
at
com.sun.corba.se.internal.iiop.CDRInputStream_1_0.read_octet_array(CDRInputS
tream_1_0.java:586)
at
com.sun.corba.se.internal.iiop.CDRInputStream.read_octet_array(CDRInputStrea
m.java:217)
at
com.coremedia.corba.DefragHang$MyServant._invoke(DefragHang.java:68)
at
com.sun.corba.se.internal.POA.GenericPOAServerSC.dispatchToServant(GenericPO
AServerSC.java:517)
at
com.sun.corba.se.internal.POA.GenericPOAServerSC.internalDispatch(GenericPOA
ServerSC.java:207)
at
com.sun.corba.se.internal.POA.GenericPOAServerSC.dispatch(GenericPOAServerSC
.java:109)
at com.sun.corba.se.internal.iiop.ORB.process(ORB.java:280)
at
com.sun.corba.se.internal.iiop.RequestProcessor.process(RequestProcessor.jav
a:81)
at
com.sun.corba.se.internal.orbutil.ThreadPool$PooledThread.run(ThreadPool.jav
a:106)
REPRODUCIBILITY :
This bug can be reproduced occasionally.
---------- BEGIN SOURCE ----------
/*
* Copyright (c) 2006 CoreMedia AG, Hamburg. All rights reserved.
*/
package com.coremedia.corba;
import org.omg.CORBA.ORB;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.portable.*;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper; import
org.omg.PortableServer.Servant;
import java.util.Properties;
public class DefragHang {
static final String[] ORB_INIT_ARGS = {}; // {"-ORBDebug", "transport"};
public static void main(String[] args) throws /*a lot of*/ Exception {
if(args.length == 0) {
// server, poa, servant
ORB server = ORB.init(ORB_INIT_ARGS, new Properties());
POA poa =
POAHelper.narrow(server.resolve_initial_references("RootPOA"));
poa.the_POAManager().activate();
byte[] oid = poa.activate_object(new MyServant());
org.omg.CORBA.Object reference = poa.id_to_reference(oid);
String ior = server.object_to_string(reference);
System.out.println(ior);
System.out.println("press any key to shut down...");
System.in.read();
// shutdown will hang waiting for the unfinished fragmented call
System.out.println("shutting down...");
server.shutdown(true);
System.out.println("shut down.");
} else {
String ior = args[0];
// client, stub
ORB client = ORB.init(new String[0], new Properties());
ObjectImpl stub = (ObjectImpl) client.string_to_object(ior);
// make request big enough to provoke fragmentation
byte[] payload = new byte[1024];
OutputStream request = stub._request("callme", true);
request.write_long(payload.length);
request.write_octet_array(payload, 0, payload.length);
if(args.length > 1) {
// this is the interesting case - server thread remains stuck in
read_octet_array
// because last fragment never arrives
System.exit(0);
}
InputStream reply = stub._invoke(request);
stub._releaseReply(reply);
client.shutdown(true);
}
}
static class MyServant extends Servant implements InvokeHandler {
public String[] _all_interfaces(POA poa, byte[] objectId) {
return new String[] { "IDL:egal:1.0" };
}
public OutputStream _invoke(String method, InputStream input,
ResponseHandler handler) throws SystemException {
System.out.println("incoming call...");
try {
int length = input.read_long();
byte[] payload = new byte[length];
input.read_octet_array(payload, 0, length);
System.out.println("call to "+method+" received with
"+payload.length+" bytes");
return handler.createReply();
} finally {
System.out.println("...call handled");
}
}
}
}
---------- END SOURCE ----------