Browse Source

AbstractDiskWriter::closeFile(): Throw exception if close() failed.

~AbstractDiskWriter calles closeFile(), but suppresses exception.
MultiDiskAdaptor::closeFile() logs error if child
DiskWriter::closeFile() throws exception. This exception is not
rethrown. If at least one exception is caught,
MultiDiskAdaptor::closeFile() throws new DlAbortEx.
RequestGroupMan::closeFile() just logs exception and suppress each
exception. Generally, don't call closeFile() in destructor. If you
need to call it, it must suppress the exception.
Tatsuhiro Tsujikawa 14 năm trước cách đây
mục cha
commit
d5ffa2532d
3 tập tin đã thay đổi với 31 bổ sung5 xóa
  1. 12 2
      src/AbstractDiskWriter.cc
  2. 14 2
      src/MultiDiskAdaptor.cc
  3. 5 1
      src/RequestGroupMan.cc

+ 12 - 2
src/AbstractDiskWriter.cc

@@ -59,7 +59,10 @@ AbstractDiskWriter::AbstractDiskWriter(const std::string& filename)
 
 AbstractDiskWriter::~AbstractDiskWriter()
 {
-  closeFile();
+  try {
+    closeFile();
+  } catch(...) {
+  }
 }
 
 void AbstractDiskWriter::openFile(off_t totalLength)
@@ -78,8 +81,15 @@ void AbstractDiskWriter::openFile(off_t totalLength)
 void AbstractDiskWriter::closeFile()
 {
   if(fd_ >= 0) {
-    close(fd_);
+    int r;
+    while((r = close(fd_)) == -1 && errno == EINTR);
     fd_ = -1;
+    if(r == -1) {
+      int errNum = errno;
+      throw DL_ABORT_EX3(errNum, fmt("Failed to close file: %s",
+                                     util::safeStrerror(errNum).c_str()),
+                         error_code::FILE_IO_ERROR);
+    }
   }
 }
 

+ 14 - 2
src/MultiDiskAdaptor.cc

@@ -297,8 +297,20 @@ void MultiDiskAdaptor::openExistingFile()
 
 void MultiDiskAdaptor::closeFile()
 {
-  std::for_each(diskWriterEntries_.begin(), diskWriterEntries_.end(),
-                mem_fun_sh(&DiskWriterEntry::closeFile));
+  bool ok = true;
+  for(std::vector<SharedHandle<DiskWriterEntry> >::const_iterator i =
+        diskWriterEntries_.begin(), eoi = diskWriterEntries_.end(); i != eoi;
+      ++i) {
+    try {
+      (*i)->closeFile();
+    } catch(RecoverableException& e) {
+      A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e);
+      ok = false;
+    }
+  }
+  if(!ok) {
+    throw DL_ABORT_EX("Failed to close some files");
+  }
 }
 
 namespace {

+ 5 - 1
src/RequestGroupMan.cc

@@ -554,7 +554,11 @@ void RequestGroupMan::closeFile()
 {
   for(std::deque<SharedHandle<RequestGroup> >::const_iterator itr =
         requestGroups_.begin(), eoi = requestGroups_.end(); itr != eoi; ++itr) {
-    (*itr)->closeFile();
+    try {
+      (*itr)->closeFile();
+    } catch(RecoverableException& e) {
+      A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e);
+    }
   }
 }