From 22ada0cf3251047ddd7a43ec6f2b2553aa0902b7 Mon Sep 17 00:00:00 2001
From: Tatsuhiro Tsujikawa <tatsuhiro.t@gmail.com>
Date: Tue, 1 Jun 2010 12:40:57 +0000
Subject: [PATCH] 2010-06-01  Tatsuhiro Tsujikawa 
 <t-tujikawa@users.sourceforge.net>

	Fixed double memory free when Exception raised from
	AbstractCommand::prepareForNextAction() called by
	HttpResponseCommand::handleDefaultEncoding().
	* src/AbstractCommand.cc
	* src/HttpResponseCommand.cc
---
 ChangeLog                  |  8 +++++
 src/AbstractCommand.cc     |  3 ++
 src/HttpResponseCommand.cc | 60 ++++++++++++++++++--------------------
 3 files changed, 39 insertions(+), 32 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 71103dae..69ec2063 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2010-06-01  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
+
+	Fixed double memory free when Exception raised from
+	AbstractCommand::prepareForNextAction() called by
+	HttpResponseCommand::handleDefaultEncoding().
+	* src/AbstractCommand.cc
+	* src/HttpResponseCommand.cc
+
 2010-06-01  Tatsuhiro Tsujikawa  <t-tujikawa@users.sourceforge.net>
 
 	Added _logger->info() guard
diff --git a/src/AbstractCommand.cc b/src/AbstractCommand.cc
index b11a37fe..337babdd 100644
--- a/src/AbstractCommand.cc
+++ b/src/AbstractCommand.cc
@@ -697,6 +697,9 @@ std::string AbstractCommand::resolveHostname
   return ipaddr;
 }
 
+// nextCommand is going to be managed by CheckIntegrityEntry which is
+// created in side this function. Don't release nextCommand after this
+// function call.
 void AbstractCommand::prepareForNextAction(Command* nextCommand)
 {
   SharedHandle<CheckIntegrityEntry> entry
diff --git a/src/HttpResponseCommand.cc b/src/HttpResponseCommand.cc
index 6bee2be0..b316128b 100644
--- a/src/HttpResponseCommand.cc
+++ b/src/HttpResponseCommand.cc
@@ -233,39 +233,35 @@ bool HttpResponseCommand::handleDefaultEncoding
 
     return true;
   }
-
+  _requestGroup->loadAndOpenFile(infoFile);
+  File file(_requestGroup->getFirstFilePath());
+  // We have to make sure that command that has Request object must
+  // have segment after PieceStorage is initialized. See
+  // AbstractCommand::execute()
+  SharedHandle<Segment> segment =
+    _requestGroup->getSegmentMan()->getSegment(cuid, 0);
+  // pipelining requires implicit range specified. But the request for
+  // this response most likely dones't contains range header. This means
+  // we can't continue to use this socket because server sends all entity
+  // body instead of a segment.
+  // Therefore, we shutdown the socket here if pipelining is enabled.
   DownloadCommand* command = 0;
-  try {
-    _requestGroup->loadAndOpenFile(infoFile);
-    File file(_requestGroup->getFirstFilePath());
-
-    // We have to make sure that command that has Request object must
-    // have segment after PieceStorage is initialized. See
-    // AbstractCommand::execute()
-    SharedHandle<Segment> segment =
-      _requestGroup->getSegmentMan()->getSegment(cuid, 0);
-    // pipelining requires implicit range specified. But the request for
-    // this response most likely dones't contains range header. This means
-    // we can't continue to use this socket because server sends all entity
-    // body instead of a segment.
-    // Therefore, we shutdown the socket here if pipelining is enabled.
-    if(req->getMethod() == Request::METHOD_GET &&
-       !segment.isNull() && segment->getPositionToWrite() == 0 &&
-       !req->isPipeliningEnabled()) {
-      command = createHttpDownloadCommand
-        (httpResponse, getTransferEncodingDecoder(httpResponse));
-    } else {
-      _requestGroup->getSegmentMan()->cancelSegment(cuid);
-      _fileEntry->poolRequest(req);
-    }
-    prepareForNextAction(command);
-    if(req->getMethod() == Request::METHOD_HEAD) {
-      poolConnection();
-      req->setMethod(Request::METHOD_GET);
-    }
-  } catch(Exception& e) {
-    delete command;
-    throw;
+  if(req->getMethod() == Request::METHOD_GET &&
+     !segment.isNull() && segment->getPositionToWrite() == 0 &&
+     !req->isPipeliningEnabled()) {
+    command = createHttpDownloadCommand
+      (httpResponse, getTransferEncodingDecoder(httpResponse));
+  } else {
+    _requestGroup->getSegmentMan()->cancelSegment(cuid);
+    _fileEntry->poolRequest(req);
+  }
+  // After command is passed to prepareForNextAction(), it is managed
+  // by CheckIntegrityEntry.
+  prepareForNextAction(command);
+  command = 0;
+  if(req->getMethod() == Request::METHOD_HEAD) {
+    poolConnection();
+    req->setMethod(Request::METHOD_GET);
   }
   return true;
 }