From 34d1b39c7525898b43e44a7c5cbd86768714baf0 Mon Sep 17 00:00:00 2001 From: Hairong Kuang Date: Tue, 26 Jan 2010 22:55:17 +0000 Subject: [PATCH] HADOOP-6498. IPC client bug may cause rpc call hang. Contributed by Ruyue Ma and Hairong Kuang. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@903471 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 3 ++ src/java/org/apache/hadoop/ipc/Client.java | 3 +- .../core/org/apache/hadoop/ipc/TestIPC.java | 42 +++++++++++++++++-- 3 files changed, 44 insertions(+), 4 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index f03a1b46dd4..ac245292602 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1320,6 +1320,9 @@ Release 0.20.2 - Unreleased HADOOP-6315. Avoid incorrect use of BuiltInflater/BuiltInDeflater in GzipCodec. (Aaron Kimball via cdouglas) + HADOOP-6498. IPC client bug may cause rpc call hang. (Ruyue Ma and + hairong via hairong) + Release 0.20.1 - 2009-09-01 INCOMPATIBLE CHANGES diff --git a/src/java/org/apache/hadoop/ipc/Client.java b/src/java/org/apache/hadoop/ipc/Client.java index f71a4a507a4..4932a8d14f7 100644 --- a/src/java/org/apache/hadoop/ipc/Client.java +++ b/src/java/org/apache/hadoop/ipc/Client.java @@ -529,13 +529,14 @@ private void receiveResponse() { if (LOG.isDebugEnabled()) LOG.debug(getName() + " got value #" + id); - Call call = calls.remove(id); + Call call = calls.get(id); int state = in.readInt(); // read call status if (state == Status.SUCCESS.state) { Writable value = ReflectionUtils.newInstance(valueClass, conf); value.readFields(in); // read value call.setValue(value); + calls.remove(id); } else if (state == Status.ERROR.state) { call.setException(new RemoteException(WritableUtils.readString(in), WritableUtils.readString(in))); diff --git a/src/test/core/org/apache/hadoop/ipc/TestIPC.java b/src/test/core/org/apache/hadoop/ipc/TestIPC.java index df5a1558153..16e1cbe576c 100644 --- a/src/test/core/org/apache/hadoop/ipc/TestIPC.java +++ b/src/test/core/org/apache/hadoop/ipc/TestIPC.java @@ -26,6 +26,7 @@ import org.apache.hadoop.net.NetUtils; import java.util.Random; +import java.io.DataInput; import java.io.IOException; import java.net.InetSocketAddress; @@ -88,7 +89,7 @@ public void run() { try { LongWritable param = new LongWritable(RANDOM.nextLong()); LongWritable value = - (LongWritable)client.call(param, server); + (LongWritable)client.call(param, server, null, null); if (!param.equals(value)) { LOG.fatal("Call failed!"); failed = true; @@ -121,7 +122,7 @@ public void run() { Writable[] params = new Writable[addresses.length]; for (int j = 0; j < addresses.length; j++) params[j] = new LongWritable(RANDOM.nextLong()); - Writable[] values = client.call(params, addresses); + Writable[] values = client.call(params, addresses, null, null); for (int j = 0; j < addresses.length; j++) { if (!params[j].equals(values[j])) { LOG.fatal("Call failed!"); @@ -216,7 +217,7 @@ public void testStandAloneClient() throws Exception { InetSocketAddress address = new InetSocketAddress("127.0.0.1", 10); try { client.call(new LongWritable(RANDOM.nextLong()), - address); + address, null, null); fail("Expected an exception to have been thrown"); } catch (IOException e) { String message = e.getMessage(); @@ -231,6 +232,41 @@ public void testStandAloneClient() throws Exception { } } + private static class LongErrorWritable extends LongWritable { + private final static String ERR_MSG = + "Come across an exception while reading"; + + LongErrorWritable() {} + + LongErrorWritable(long longValue) { + super(longValue); + } + + public void readFields(DataInput in) throws IOException { + super.readFields(in); + throw new IOException(ERR_MSG); + } + } + public void testErrorClient() throws Exception { + // start server + Server server = new TestServer(1, false); + InetSocketAddress addr = NetUtils.getConnectAddress(server); + server.start(); + + // start client + Client client = new Client(LongErrorWritable.class, conf); + try { + client.call(new LongErrorWritable(RANDOM.nextLong()), + addr, null, null); + fail("Expected an exception to have been thrown"); + } catch (IOException e) { + // check error + Throwable cause = e.getCause(); + assertTrue(cause instanceof IOException); + assertEquals(LongErrorWritable.ERR_MSG, cause.getMessage()); + } + } + public static void main(String[] args) throws Exception {