From 228b4c50d757b80efe493728a658ae145eaf67ef Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Tue, 9 Nov 2010 14:43:47 +0000 Subject: [PATCH] 2010-11-09 Tatsuhiro Tsujikawa Capture errno right after system/library call to avoid it to get overwritten. Use util::safeStrerror instead of strerror directly because strerror might return NULL. We don't check errno for std::fstream anymore. * src/AbstractDiskWriter.cc * src/CookieStorage.cc * src/DHTAutoSaveCommand.cc * src/DHTRoutingTableDeserializer.cc * src/DHTRoutingTableSerializer.cc * src/DefaultBtProgressInfoFile.cc * src/EpollEventPoll.cc * src/IteratableChunkChecksumValidator.cc * src/KqueueEventPoll.cc * src/Logger.cc * src/MessageDigestHelper.cc * src/PortEventPoll.cc * src/SelectEventPoll.cc * src/SocketCore.cc * src/message.h * src/util.cc * src/util.h --- ChangeLog | 24 ++++ src/AbstractDiskWriter.cc | 49 +++++--- src/CookieStorage.cc | 6 +- src/DHTAutoSaveCommand.cc | 5 +- src/DHTRoutingTableDeserializer.cc | 5 +- src/DHTRoutingTableSerializer.cc | 5 +- src/DefaultBtProgressInfoFile.cc | 28 ++--- src/EpollEventPoll.cc | 18 ++- src/IteratableChunkChecksumValidator.cc | 3 +- src/KqueueEventPoll.cc | 12 +- src/Logger.cc | 3 +- src/MessageDigestHelper.cc | 11 +- src/PortEventPoll.cc | 19 +++- src/SelectEventPoll.cc | 22 +--- src/SocketCore.cc | 141 ++++++++++++++++-------- src/message.h | 5 +- src/util.cc | 28 ++++- src/util.h | 8 ++ 18 files changed, 256 insertions(+), 136 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5fb10463..fe8100b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,27 @@ +2010-11-09 Tatsuhiro Tsujikawa + + Capture errno right after system/library call to avoid it to get + overwritten. Use util::safeStrerror instead of strerror directly + because strerror might return NULL. We don't check errno for + std::fstream anymore. + * src/AbstractDiskWriter.cc + * src/CookieStorage.cc + * src/DHTAutoSaveCommand.cc + * src/DHTRoutingTableDeserializer.cc + * src/DHTRoutingTableSerializer.cc + * src/DefaultBtProgressInfoFile.cc + * src/EpollEventPoll.cc + * src/IteratableChunkChecksumValidator.cc + * src/KqueueEventPoll.cc + * src/Logger.cc + * src/MessageDigestHelper.cc + * src/PortEventPoll.cc + * src/SelectEventPoll.cc + * src/SocketCore.cc + * src/message.h + * src/util.cc + * src/util.h + 2010-11-07 Tatsuhiro Tsujikawa Use const reference diff --git a/src/AbstractDiskWriter.cc b/src/AbstractDiskWriter.cc index fd00d649..066c4e35 100644 --- a/src/AbstractDiskWriter.cc +++ b/src/AbstractDiskWriter.cc @@ -99,10 +99,12 @@ void AbstractDiskWriter::openExistingFile(uint64_t totalLength) } if((fd_ = open(filename_.c_str(), flags, OPEN_MODE)) < 0) { + int errNum = errno; throw DL_ABORT_EX2 - (errno, - StringFormat - (EX_FILE_OPEN, filename_.c_str(), strerror(errno)).str()); + (errNum, + StringFormat(EX_FILE_OPEN, + filename_.c_str(), + util::safeStrerror(errNum).c_str()).str()); } } @@ -112,9 +114,12 @@ void AbstractDiskWriter::createFile(int addFlags) util::mkdirs(File(filename_).getDirname()); if((fd_ = open(filename_.c_str(), O_CREAT|O_RDWR|O_TRUNC|O_BINARY|addFlags, OPEN_MODE)) < 0) { + int errNum = errno; throw DL_ABORT_EX2 - (errno, - StringFormat(EX_FILE_OPEN, filename_.c_str(), strerror(errno)).str()); + (errNum, + StringFormat(EX_FILE_OPEN, + filename_.c_str(), + util::safeStrerror(errNum).c_str()).str()); } } @@ -142,8 +147,11 @@ ssize_t AbstractDiskWriter::readDataInternal(unsigned char* data, size_t len) void AbstractDiskWriter::seek(off_t offset) { if(a2lseek(fd_, offset, SEEK_SET) == (off_t)-1) { + int errNum = errno; throw DL_ABORT_EX - (StringFormat(EX_FILE_SEEK, filename_.c_str(), strerror(errno)).str()); + (StringFormat(EX_FILE_SEEK, + filename_.c_str(), + util::safeStrerror(errNum).c_str()).str()); } } @@ -151,14 +159,20 @@ void AbstractDiskWriter::writeData(const unsigned char* data, size_t len, off_t { seek(offset); if(writeDataInternal(data, len) < 0) { + int errNum = errno; // If errno is ENOSPC(not enough space in device), throw // DownloadFailureException and abort download instantly. - if(errno == ENOSPC) { + if(errNum == ENOSPC) { throw DOWNLOAD_FAILURE_EXCEPTION - (StringFormat(EX_FILE_WRITE, filename_.c_str(), strerror(errno)).str()); + (StringFormat(EX_FILE_WRITE, + filename_.c_str(), + util::safeStrerror(errNum).c_str()).str()); + } else { + throw DL_ABORT_EX + (StringFormat(EX_FILE_WRITE, + filename_.c_str(), + util::safeStrerror(errNum).c_str()).str()); } - throw DL_ABORT_EX(StringFormat(EX_FILE_WRITE, - filename_.c_str(), strerror(errno)).str()); } } @@ -167,8 +181,11 @@ ssize_t AbstractDiskWriter::readData(unsigned char* data, size_t len, off_t offs ssize_t ret; seek(offset); if((ret = readDataInternal(data, len)) < 0) { - throw DL_ABORT_EX(StringFormat(EX_FILE_READ, - filename_.c_str(), strerror(errno)).str()); + int errNum = errno; + throw DL_ABORT_EX + (StringFormat(EX_FILE_READ, + filename_.c_str(), + util::safeStrerror(errNum).c_str()).str()); } return ret; } @@ -189,8 +206,9 @@ void AbstractDiskWriter::truncate(uint64_t length) } #else if(ftruncate(fd_, length) == -1) { + int errNum = errno; throw DL_ABORT_EX(StringFormat("ftruncate failed. cause: %s", - strerror(errno)).str()); + util::safeStrerror(errNum).c_str()).str()); } #endif } @@ -205,15 +223,16 @@ void AbstractDiskWriter::allocate(off_t offset, uint64_t length) // For linux, we use fallocate to detect file system supports // fallocate or not. int r = fallocate(fd_, 0, offset, length); + int errNum = errno; if(r == -1) { throw DL_ABORT_EX(StringFormat("fallocate failed. cause: %s", - strerror(errno)).str()); + util::safeStrerror(errNum).c_str()).str()); } # elif HAVE_POSIX_FALLOCATE int r = posix_fallocate(fd_, offset, length); if(r != 0) { throw DL_ABORT_EX(StringFormat("posix_fallocate failed. cause: %s", - strerror(r)).str()); + util::safeStrerror(r).c_str()).str()); } # else # error "no *_fallocate function available." diff --git a/src/CookieStorage.cc b/src/CookieStorage.cc index 40cf5544..c1d451bb 100644 --- a/src/CookieStorage.cc +++ b/src/CookieStorage.cc @@ -343,8 +343,7 @@ bool CookieStorage::saveNsFormat(const std::string& filename) { std::ofstream o(tempfilename.c_str(), std::ios::binary); if(!o) { - logger_->error("Cannot create cookie file %s, cause %s", - filename.c_str(), strerror(errno)); + logger_->error("Cannot create cookie file %s", filename.c_str()); return false; } for(std::deque::const_iterator i = domains_.begin(), @@ -353,8 +352,7 @@ bool CookieStorage::saveNsFormat(const std::string& filename) } o.flush(); if(!o) { - logger_->error("Failed to save cookies to %s, cause %s", - filename.c_str(), strerror(errno)); + logger_->error("Failed to save cookies to %s", filename.c_str()); return false; } } diff --git a/src/DHTAutoSaveCommand.cc b/src/DHTAutoSaveCommand.cc index 7be49920..4ceda309 100644 --- a/src/DHTAutoSaveCommand.cc +++ b/src/DHTAutoSaveCommand.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "DHTAutoSaveCommand.h" -#include #include #include @@ -117,8 +116,8 @@ void DHTAutoSaveCommand::save() std::ios::out|std::ios::binary); if(!o) { throw DL_ABORT_EX - (StringFormat("Failed to save DHT routing table to %s. cause:%s", - dhtFile.c_str(), strerror(errno)).str()); + (StringFormat("Failed to save DHT routing table to %s.", + dhtFile.c_str()).str()); } serializer.serialize(o); } diff --git a/src/DHTRoutingTableDeserializer.cc b/src/DHTRoutingTableDeserializer.cc index ee73736a..6ed09d08 100644 --- a/src/DHTRoutingTableDeserializer.cc +++ b/src/DHTRoutingTableDeserializer.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "DHTRoutingTableDeserializer.h" -#include #include #include #include @@ -73,9 +72,7 @@ void readBytes(unsigned char* buf, size_t buflen, "Unexpected EOF").str()); \ } \ if(!in) { \ - throw DL_ABORT_EX \ - (StringFormat("Failed to load DHT routing table. cause:%s", \ - strerror(errno)).str()); \ + throw DL_ABORT_EX("Failed to load DHT routing table."); \ } void DHTRoutingTableDeserializer::deserialize(std::istream& in) diff --git a/src/DHTRoutingTableSerializer.cc b/src/DHTRoutingTableSerializer.cc index 2228e422..aa995fc7 100644 --- a/src/DHTRoutingTableSerializer.cc +++ b/src/DHTRoutingTableSerializer.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "DHTRoutingTableSerializer.h" -#include #include #include @@ -130,9 +129,7 @@ void DHTRoutingTableSerializer::serialize(std::ostream& o) o.flush(); if(!o) { - throw DL_ABORT_EX - (StringFormat("Failed to save DHT routing table. cause:%s", - strerror(errno)).str()); + throw DL_ABORT_EX("Failed to save DHT routing table."); } } diff --git a/src/DefaultBtProgressInfoFile.cc b/src/DefaultBtProgressInfoFile.cc index 4fae8fbc..b35837d3 100644 --- a/src/DefaultBtProgressInfoFile.cc +++ b/src/DefaultBtProgressInfoFile.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "DefaultBtProgressInfoFile.h" -#include #include #include @@ -111,8 +110,8 @@ void DefaultBtProgressInfoFile::save() { std::ofstream o(filenameTemp.c_str(), std::ios::out|std::ios::binary); if(!o) { - throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_WRITE, - filename_.c_str(), strerror(errno)).str()); + throw DL_ABORT_EX + (StringFormat(EX_SEGMENT_FILE_WRITE, filename_.c_str()).str()); } #ifdef ENABLE_BITTORRENT bool torrentDownload = isTorrentDownload(); @@ -199,25 +198,26 @@ void DefaultBtProgressInfoFile::save() } o.flush(); if(!o) { - throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_WRITE, - filename_.c_str(), strerror(errno)).str()); + throw DL_ABORT_EX + (StringFormat(EX_SEGMENT_FILE_WRITE, filename_.c_str()).str()); } logger_->info(MSG_SAVED_SEGMENT_FILE); } if(!File(filenameTemp).renameTo(filename_)) { - throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_WRITE, - filename_.c_str(), strerror(errno)).str()); + throw DL_ABORT_EX + (StringFormat(EX_SEGMENT_FILE_WRITE, filename_.c_str()).str()); } } #define CHECK_STREAM(in, length) \ if(in.gcount() != length) { \ - throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_READ, \ - filename_.c_str(),"Unexpected EOF").str()); \ + throw DL_ABORT_EX(StringFormat("Failed to read segment file %s." \ + " Unexpected EOF.", \ + filename_.c_str()).str()); \ } \ if(!in) { \ - throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_READ, \ - filename_.c_str(), strerror(errno)).str()); \ + throw DL_ABORT_EX \ + (StringFormat(EX_SEGMENT_FILE_READ, filename_.c_str()).str()); \ } // It is assumed that integers are saved as: @@ -227,9 +227,9 @@ void DefaultBtProgressInfoFile::load() { logger_->info(MSG_LOADING_SEGMENT_FILE, filename_.c_str()); std::ifstream in(filename_.c_str(), std::ios::in|std::ios::binary); - if(!in) { \ - throw DL_ABORT_EX(StringFormat(EX_SEGMENT_FILE_READ, \ - filename_.c_str(), strerror(errno)).str()); + if(!in) { + throw DL_ABORT_EX + (StringFormat(EX_SEGMENT_FILE_READ, filename_.c_str()).str()); } unsigned char versionBuf[2]; in.read(reinterpret_cast(versionBuf), sizeof(versionBuf)); diff --git a/src/EpollEventPoll.cc b/src/EpollEventPoll.cc index abd2960e..75db479d 100644 --- a/src/EpollEventPoll.cc +++ b/src/EpollEventPoll.cc @@ -34,6 +34,7 @@ /* copyright --> */ #include "EpollEventPoll.h" +#include #include #include #include @@ -41,6 +42,7 @@ #include "Command.h" #include "LogFactory.h" #include "Logger.h" +#include "util.h" namespace aria2 { @@ -90,10 +92,11 @@ EpollEventPoll::~EpollEventPoll() if(epfd_ != -1) { int r; while((r = close(epfd_)) == -1 && errno == EINTR); + int errNum = errno; if(r == -1) { logger_->error("Error occurred while closing epoll file descriptor" " %d: %s", - epfd_, strerror(errno)); + epfd_, util::safeStrerror(errNum).c_str()); } } delete [] epEvents_; @@ -165,6 +168,7 @@ bool EpollEventPoll::addEvents(sock_t socket, std::deque >::iterator i = std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry); int r = 0; + int errNum = 0; if(i != socketEntries_.end() && (*i) == socketEntry) { event.addSelf(*i); @@ -178,6 +182,7 @@ bool EpollEventPoll::addEvents(sock_t socket, r = epoll_ctl(epfd_, EPOLL_CTL_ADD, (*i)->getSocket(), &epEvent); + errNum = errno; } } else { socketEntries_.insert(i, socketEntry); @@ -191,11 +196,12 @@ bool EpollEventPoll::addEvents(sock_t socket, struct epoll_event epEvent = socketEntry->getEvents(); r = epoll_ctl(epfd_, EPOLL_CTL_ADD, socketEntry->getSocket(), &epEvent); + errNum = errno; } if(r == -1) { if(logger_->debug()) { logger_->debug("Failed to add socket event %d:%s", - socket, strerror(errno)); + socket, util::safeStrerror(errNum).c_str()); } return false; } else { @@ -229,27 +235,31 @@ bool EpollEventPoll::deleteEvents(sock_t socket, event.removeSelf(*i); int r = 0; + int errNum = 0; if((*i)->eventEmpty()) { // In kernel before 2.6.9, epoll_ctl with EPOLL_CTL_DEL requires non-null // pointer of epoll_event. struct epoll_event ev = {0,{0}}; r = epoll_ctl(epfd_, EPOLL_CTL_DEL, (*i)->getSocket(), &ev); + errNum = r; socketEntries_.erase(i); } else { // If socket is closed, then it seems it is automatically removed from // epoll, so following EPOLL_CTL_MOD may fail. struct epoll_event epEvent = (*i)->getEvents(); r = epoll_ctl(epfd_, EPOLL_CTL_MOD, (*i)->getSocket(), &epEvent); + errNum = r; if(r == -1) { if(logger_->debug()) { logger_->debug("Failed to delete socket event, but may be ignored:%s", - strerror(errno)); + util::safeStrerror(errNum).c_str()); } } } if(r == -1) { if(logger_->debug()) { - logger_->debug("Failed to delete socket event:%s", strerror(errno)); + logger_->debug("Failed to delete socket event:%s", + util::safeStrerror(errNum).c_str()); } return false; } else { diff --git a/src/IteratableChunkChecksumValidator.cc b/src/IteratableChunkChecksumValidator.cc index 3a0dd34b..d1d7f1a3 100644 --- a/src/IteratableChunkChecksumValidator.cc +++ b/src/IteratableChunkChecksumValidator.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "IteratableChunkChecksumValidator.h" -#include #include #include @@ -161,7 +160,7 @@ std::string IteratableChunkChecksumValidator::digest(off_t offset, size_t length if(r == 0 || r < static_cast(woffset)) { throw DL_ABORT_EX (StringFormat(EX_FILE_READ, dctx_->getBasePath().c_str(), - strerror(errno)).str()); + "data is too short").str()); } size_t wlength; if(max < static_cast(curoffset+r)) { diff --git a/src/KqueueEventPoll.cc b/src/KqueueEventPoll.cc index 6b211b5a..be4b7a5a 100644 --- a/src/KqueueEventPoll.cc +++ b/src/KqueueEventPoll.cc @@ -34,6 +34,7 @@ /* copyright --> */ #include "KqueueEventPoll.h" +#include #include #include #include @@ -41,6 +42,7 @@ #include "Command.h" #include "LogFactory.h" #include "Logger.h" +#include "util.h" #ifdef KEVENT_UDATA_INTPTR_T # define PTR_TO_UDATA(X) (reinterpret_cast(X)) @@ -96,10 +98,11 @@ KqueueEventPoll::~KqueueEventPoll() if(kqfd_ != -1) { int r; while((r = close(kqfd_)) == -1 && errno == EINTR); + int errNum = errno; if(r == -1) { logger_->error("Error occurred while closing kqueue file descriptor" " %d: %s", - kqfd_, strerror(errno)); + kqfd_, util::safeStrerror(errNum).c_str()); } } delete [] kqEvents_; @@ -186,10 +189,11 @@ bool KqueueEventPoll::addEvents n = socketEntry->getEvents(changelist); } r = kevent(kqfd_, changelist, n, changelist, 0, &zeroTimeout); + int errNum = errno; if(r == -1) { if(logger_->debug()) { logger_->debug("Failed to add socket event %d:%s", - socket, strerror(errno)); + socket, util::safeStrerror(errNum).c_str()); } return false; } else { @@ -225,12 +229,14 @@ bool KqueueEventPoll::deleteEvents(sock_t socket, struct kevent changelist[2]; size_t n = (*i)->getEvents(changelist); r = kevent(kqfd_, changelist, n, changelist, 0, &zeroTimeout); + int errNum = errno; if((*i)->eventEmpty()) { socketEntries_.erase(i); } if(r == -1) { if(logger_->debug()) { - logger_->debug("Failed to delete socket event:%s", strerror(errno)); + logger_->debug("Failed to delete socket event:%s", + util::safeStrerror(errNum).c_str()); } return false; } else { diff --git a/src/Logger.cc b/src/Logger.cc index 6048f450..120d65d9 100644 --- a/src/Logger.cc +++ b/src/Logger.cc @@ -34,7 +34,6 @@ /* copyright --> */ #include "Logger.h" -#include #include #include "DlAbortEx.h" @@ -68,7 +67,7 @@ void Logger::openFile(const std::string& filename) file_.open(filename.c_str(), std::ios::app|std::ios::binary); if(!file_) { throw DL_ABORT_EX - (StringFormat(EX_FILE_OPEN, filename.c_str(), strerror(errno)).str()); + (StringFormat(EX_FILE_OPEN, filename.c_str(), "n/a").str()); } } diff --git a/src/MessageDigestHelper.cc b/src/MessageDigestHelper.cc index 5ffd40b1..22b3bf31 100644 --- a/src/MessageDigestHelper.cc +++ b/src/MessageDigestHelper.cc @@ -33,15 +33,16 @@ */ /* copyright --> */ #include "MessageDigestHelper.h" + +#include +#include + #include "messageDigest.h" #include "DlAbortEx.h" #include "message.h" #include "DefaultDiskWriter.h" #include "util.h" #include "StringFormat.h" -#include -#include -#include namespace aria2 { @@ -92,7 +93,7 @@ std::string MessageDigestHelper::digest(MessageDigestContext* ctx, ssize_t readLength = bs->readData(BUF, BUFSIZE, offset); if((size_t)readLength != BUFSIZE) { throw DL_ABORT_EX - (StringFormat(EX_FILE_READ, "n/a", strerror(errno)).str()); + (StringFormat(EX_FILE_READ, "n/a", "data is too short").str()); } ctx->digestUpdate(BUF, readLength); offset += readLength; @@ -101,7 +102,7 @@ std::string MessageDigestHelper::digest(MessageDigestContext* ctx, ssize_t readLength = bs->readData(BUF, tail, offset); if((size_t)readLength != tail) { throw DL_ABORT_EX - (StringFormat(EX_FILE_READ, "n/a", strerror(errno)).str()); + (StringFormat(EX_FILE_READ, "n/a", "data is too short").str()); } ctx->digestUpdate(BUF, readLength); } diff --git a/src/PortEventPoll.cc b/src/PortEventPoll.cc index 91335b15..cb3757cd 100644 --- a/src/PortEventPoll.cc +++ b/src/PortEventPoll.cc @@ -34,6 +34,7 @@ /* copyright --> */ #include "PortEventPoll.h" +#include #include #include #include @@ -41,6 +42,7 @@ #include "Command.h" #include "LogFactory.h" #include "Logger.h" +#include "util.h" namespace aria2 { @@ -85,9 +87,10 @@ PortEventPoll::~PortEventPoll() if(port_ != -1) { int r; while((r = close(port_)) == -1 && errno == EINTR); + int errNum = errno; if(r == -1) { logger_->error("Error occurred while closing port %d: %s", - port_, strerror(errno)); + port_, util::safeStrerror(errNum).c_str()); } } delete [] portEvents_; @@ -120,9 +123,10 @@ void PortEventPoll::poll(const struct timeval& tv) p->processEvents(pev.portev_events); int r = port_associate(port_, PORT_SOURCE_FD, pev.portev_object, p->getEvents().events, p); + int errNum = errno; if(r == -1) { logger_->error("port_associate failed for file descriptor %d: cause %s", - pev.portev_object, strerror(errno)); + pev.portev_object, util::safeStrerror(errNum).c_str()); } } } @@ -171,11 +175,13 @@ bool PortEventPoll::addEvents(sock_t socket, std::deque >::iterator i = std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry); int r = 0; + int errNum = 0; if(i != socketEntries_.end() && (*i) == socketEntry) { event.addSelf(*i); A2PortEvent pv = (*i)->getEvents(); r = port_associate(port_, PORT_SOURCE_FD, (*i)->getSocket(), pv.events, pv.socketEntry); + errNum = r; } else { socketEntries_.insert(i, socketEntry); if(socketEntries_.size() > portEventsSize_) { @@ -187,11 +193,12 @@ bool PortEventPoll::addEvents(sock_t socket, A2PortEvent pv = socketEntry->getEvents(); r = port_associate(port_, PORT_SOURCE_FD, socketEntry->getSocket(), pv.events, pv.socketEntry); + errNum = r; } if(r == -1) { if(logger_->debug()) { logger_->debug("Failed to add socket event %d:%s", - socket, strerror(errno)); + socket, util::safeStrerror(errNum).c_str()); } return false; } else { @@ -223,17 +230,21 @@ bool PortEventPoll::deleteEvents(sock_t socket, if(i != socketEntries_.end() && (*i) == socketEntry) { event.removeSelf(*i); int r = 0; + int errNum = 0; if((*i)->eventEmpty()) { r = port_dissociate(port_, PORT_SOURCE_FD, (*i)->getSocket()); + errNum = errno; socketEntries_.erase(i); } else { A2PortEvent pv = (*i)->getEvents(); r = port_associate(port_, PORT_SOURCE_FD, (*i)->getSocket(), pv.events, pv.socketEntry); + errNum = errno; } if(r == -1) { if(logger_->debug()) { - logger_->debug("Failed to delete socket event:%s", strerror(errno)); + logger_->debug("Failed to delete socket event:%s", + util::safeStrerror(errNum).c_str()); } return false; } else { diff --git a/src/SelectEventPoll.cc b/src/SelectEventPoll.cc index 9b3950fd..473091e3 100644 --- a/src/SelectEventPoll.cc +++ b/src/SelectEventPoll.cc @@ -40,7 +40,6 @@ #include #include #include -#include #include "Command.h" #include "LogFactory.h" @@ -280,7 +279,6 @@ bool SelectEventPoll::addEvents(sock_t socket, Command* command, SharedHandle socketEntry(new SocketEntry(socket)); std::deque >::iterator i = std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry); - int r = 0; if(i != socketEntries_.end() && (*i) == socketEntry) { (*i)->addCommandEvent(command, events); } else { @@ -288,15 +286,7 @@ bool SelectEventPoll::addEvents(sock_t socket, Command* command, socketEntry->addCommandEvent(command, events); } updateFdSet(); - if(r == -1) { - if(logger_->debug()) { - logger_->debug("Failed to add socket event %d:%s", - socket, strerror(errno)); - } - return false; - } else { - return true; - } + return true; } bool SelectEventPoll::deleteEvents(sock_t socket, Command* command, @@ -307,19 +297,11 @@ bool SelectEventPoll::deleteEvents(sock_t socket, Command* command, std::lower_bound(socketEntries_.begin(), socketEntries_.end(), socketEntry); if(i != socketEntries_.end() && (*i) == socketEntry) { (*i)->removeCommandEvent(command, events); - int r = 0; if((*i)->eventEmpty()) { socketEntries_.erase(i); } updateFdSet(); - if(r == -1) { - if(logger_->debug()) { - logger_->debug("Failed to delete socket event:%s", strerror(errno)); - } - return false; - } else { - return true; - } + return true; } else { if(logger_->debug()) { logger_->debug("Socket %d is not found in SocketEntries.", socket); diff --git a/src/SocketCore.cc b/src/SocketCore.cc index a7d196e9..f735ec01 100644 --- a/src/SocketCore.cc +++ b/src/SocketCore.cc @@ -92,32 +92,29 @@ namespace aria2 { # define CLOSE(X) while(close(X) == -1 && errno == EINTR) #endif // __MINGW32__ -static const char *errorMsg(const int err) +namespace { +std::string errorMsg(int errNum) { #ifndef __MINGW32__ - return strerror(err); + return util::safeStrerror(errNum); #else static char buf[256]; if (FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, - err, + errNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &buf, sizeof(buf), NULL ) == 0) { - snprintf(buf, sizeof(buf), EX_SOCKET_UNKNOWN_ERROR, err, err); + snprintf(buf, sizeof(buf), EX_SOCKET_UNKNOWN_ERROR, errNum, errNum); } return buf; #endif // __MINGW32__ } - -static const char *errorMsg() -{ - return errorMsg(SOCKET_ERRNO); -} +} // namespace int SocketCore::protocolFamily_ = AF_UNSPEC; @@ -170,18 +167,23 @@ SocketCore::~SocketCore() { void SocketCore::create(int family, int protocol) { + int errNum; closeConnection(); sock_t fd = socket(family, sockType_, protocol); + errNum = SOCKET_ERRNO; if(fd == (sock_t) -1) { throw DL_ABORT_EX - (StringFormat("Failed to create socket. Cause:%s", errorMsg()).str()); + (StringFormat + ("Failed to create socket. Cause:%s", errorMsg(errNum).c_str()).str()); } int sockopt = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt, sizeof(sockopt)) < 0) { + errNum = SOCKET_ERRNO; CLOSE(fd); throw DL_ABORT_EX - (StringFormat("Failed to create socket. Cause:%s", errorMsg()).str()); + (StringFormat + ("Failed to create socket. Cause:%s", errorMsg(errNum).c_str()).str()); } sockfd_ = fd; } @@ -190,13 +192,18 @@ static sock_t bindInternal(int family, int socktype, int protocol, const struct sockaddr* addr, socklen_t addrlen, std::string& error) { + int errNum; sock_t fd = socket(family, socktype, protocol); + errNum = SOCKET_ERRNO; if(fd == (sock_t) -1) { + error = errorMsg(errNum); return -1; } int sockopt = 1; if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt, sizeof(sockopt)) < 0) { + errNum = SOCKET_ERRNO; + error = errorMsg(errNum); CLOSE(fd); return -1; } @@ -205,13 +212,16 @@ static sock_t bindInternal(int family, int socktype, int protocol, int sockopt = 1; if(setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (a2_sockopt_t) &sockopt, sizeof(sockopt)) < 0) { + errNum = SOCKET_ERRNO; + error = errorMsg(errNum); CLOSE(fd); return -1; } } #endif // IPV6_V6ONLY if(::bind(fd, addr, addrlen) == -1) { - error = errorMsg(); + errNum = SOCKET_ERRNO; + error = errorMsg(errNum); CLOSE(fd); return -1; } @@ -319,7 +329,9 @@ void SocketCore::bind(const struct sockaddr* addr, socklen_t addrlen) void SocketCore::beginListen() { if(listen(sockfd_, 1) == -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_LISTEN, errorMsg()).str()); + int errNum = SOCKET_ERRNO; + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_LISTEN, errorMsg(errNum).c_str()).str()); } } @@ -328,9 +340,13 @@ SocketCore* SocketCore::acceptConnection() const struct sockaddr_storage sockaddr; socklen_t len = sizeof(sockaddr); sock_t fd; - while((fd = accept(sockfd_, reinterpret_cast(&sockaddr), &len)) == (sock_t) -1 && SOCKET_ERRNO == A2_EINTR); + while((fd = accept(sockfd_, reinterpret_cast(&sockaddr), + &len)) == (sock_t) -1 && + SOCKET_ERRNO == A2_EINTR); + int errNum = SOCKET_ERRNO; if(fd == (sock_t) -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_ACCEPT, errorMsg()).str()); + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_ACCEPT, errorMsg(errNum).c_str()).str()); } return new SocketCore(fd, sockType_); } @@ -349,7 +365,9 @@ void SocketCore::getAddrInfo { struct sockaddr* addrp = reinterpret_cast(&sockaddr); if(getsockname(sockfd_, addrp, &len) == -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str()); + int errNum = SOCKET_ERRNO; + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_GET_NAME, errorMsg(errNum).c_str()).str()); } } @@ -367,7 +385,9 @@ void SocketCore::getPeerInfo(std::pair& peerinfo) const socklen_t len = sizeof(sockaddr); struct sockaddr* addrp = reinterpret_cast(&sockaddr); if(getpeername(sockfd_, addrp, &len) == -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_GET_NAME, errorMsg()).str()); + int errNum = SOCKET_ERRNO; + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_GET_NAME, errorMsg(errNum).c_str()).str()); } peerinfo = util::getNumericNameInfo(addrp, len); } @@ -386,15 +406,19 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port) } WSAAPI_AUTO_DELETE resDeleter(res, freeaddrinfo); struct addrinfo* rp; + int errNum; for(rp = res; rp; rp = rp->ai_next) { sock_t fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + errNum = SOCKET_ERRNO; if(fd == (sock_t) -1) { - error = errorMsg(); + error = errorMsg(errNum); continue; } int sockopt = 1; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt, sizeof(sockopt)) < 0) { - error = errorMsg(); + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (a2_sockopt_t) &sockopt, + sizeof(sockopt)) < 0) { + errNum = SOCKET_ERRNO; + error = errorMsg(errNum); CLOSE(fd); continue; } @@ -405,7 +429,8 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port) i != eoi; ++i) { if(::bind(fd,reinterpret_cast(&(*i).first), (*i).second) == -1) { - error = errorMsg(); + errNum = SOCKET_ERRNO; + error = errorMsg(errNum); if(LogFactory::getInstance()->debug()) { LogFactory::getInstance()->debug(EX_SOCKET_BIND, error.c_str()); } @@ -425,7 +450,8 @@ void SocketCore::establishConnection(const std::string& host, uint16_t port) setNonBlockingMode(); if(connect(fd, rp->ai_addr, rp->ai_addrlen) == -1 && SOCKET_ERRNO != A2_EINPROGRESS) { - error = errorMsg(); + errNum = SOCKET_ERRNO; + error = errorMsg(errNum); CLOSE(sockfd_); sockfd_ = (sock_t) -1; continue; @@ -444,7 +470,9 @@ void SocketCore::setSockOpt (int level, int optname, void* optval, socklen_t optlen) { if(setsockopt(sockfd_, level, optname, (a2_sockopt_t)optval, optlen) < 0) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_SET_OPT, errorMsg()).str()); + int errNum = SOCKET_ERRNO; + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_SET_OPT, errorMsg(errNum).c_str()).str()); } } @@ -502,7 +530,9 @@ void SocketCore::setNonBlockingMode() #ifdef __MINGW32__ static u_long flag = 1; if (::ioctlsocket(sockfd_, FIONBIO, &flag) == -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_NONBLOCKING, errorMsg()).str()); + int errNum = SOCKET_ERRNO; + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_NONBLOCKING, errorMsg(errNum).c_str()).str()); } #else int flags; @@ -518,7 +548,9 @@ void SocketCore::setBlockingMode() #ifdef __MINGW32__ static u_long flag = 0; if (::ioctlsocket(sockfd_, FIONBIO, &flag) == -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_BLOCKING, errorMsg()).str()); + int errNum = SOCKET_ERRNO; + throw DL_ABORT_EX(StringFormat + (EX_SOCKET_BLOCKING, errorMsg(errNum).c_str()).str()); } #else int flags; @@ -576,13 +608,14 @@ bool SocketCore::isWritable(time_t timeout) p.events = POLLOUT; int r; while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR); + int errNum = SOCKET_ERRNO; if(r > 0) { return p.revents&(POLLOUT|POLLHUP|POLLERR); } else if(r == 0) { return false; } else { throw DL_RETRY_EX - (StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str()); + (StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg(errNum).c_str()).str()); } #else // !HAVE_POLL # ifndef __MINGW32__ @@ -597,17 +630,19 @@ bool SocketCore::isWritable(time_t timeout) tv.tv_usec = 0; int r = select(sockfd_+1, NULL, &fds, NULL, &tv); + int errNum = SOCKET_ERRNO; if(r == 1) { return true; } else if(r == 0) { // time out return false; } else { - if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) { + if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) { return false; } else { throw DL_RETRY_EX - (StringFormat(EX_SOCKET_CHECK_WRITABLE, errorMsg()).str()); + (StringFormat(EX_SOCKET_CHECK_WRITABLE, + errorMsg(errNum).c_str()).str()); } } #endif // !HAVE_POLL @@ -626,13 +661,14 @@ bool SocketCore::isReadable(time_t timeout) p.events = POLLIN; int r; while((r = poll(&p, 1, timeout*1000)) == -1 && errno == EINTR); + int errNum = SOCKET_ERRNO; if(r > 0) { return p.revents&(POLLIN|POLLHUP|POLLERR); } else if(r == 0) { return false; } else { throw DL_RETRY_EX - (StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str()); + (StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg(errNum).c_str()).str()); } #else // !HAVE_POLL # ifndef __MINGW32__ @@ -647,17 +683,19 @@ bool SocketCore::isReadable(time_t timeout) tv.tv_usec = 0; int r = select(sockfd_+1, &fds, NULL, NULL, &tv); + int errNum = SOCKET_ERRNO; if(r == 1) { return true; } else if(r == 0) { // time out return false; } else { - if(SOCKET_ERRNO == A2_EINPROGRESS || SOCKET_ERRNO == A2_EINTR) { + if(errNum == A2_EINPROGRESS || errNum == A2_EINTR) { return false; } else { throw DL_RETRY_EX - (StringFormat(EX_SOCKET_CHECK_READABLE, errorMsg()).str()); + (StringFormat(EX_SOCKET_CHECK_READABLE, + errorMsg(errNum).c_str()).str()); } } #endif // !HAVE_POLL @@ -699,12 +737,14 @@ ssize_t SocketCore::writeData(const char* data, size_t len) if(!secure_) { while((ret = send(sockfd_, data, len, 0)) == -1 && SOCKET_ERRNO == A2_EINTR); + int errNum = SOCKET_ERRNO; if(ret == -1) { - if(A2_WOULDBLOCK(SOCKET_ERRNO)) { + if(A2_WOULDBLOCK(errNum)) { wantWrite_ = true; ret = 0; } else { - throw DL_RETRY_EX(StringFormat(EX_SOCKET_SEND, errorMsg()).str()); + throw DL_RETRY_EX(StringFormat(EX_SOCKET_SEND, + errorMsg(errNum).c_str()).str()); } } } else { @@ -743,12 +783,14 @@ void SocketCore::readData(char* data, size_t& len) if(!secure_) { while((ret = recv(sockfd_, data, len, 0)) == -1 && SOCKET_ERRNO == A2_EINTR); + int errNum = SOCKET_ERRNO; if(ret == -1) { - if(A2_WOULDBLOCK(SOCKET_ERRNO)) { + if(A2_WOULDBLOCK(errNum)) { wantRead_ = true; ret = 0; } else { - throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV, errorMsg()).str()); + throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV, + errorMsg(errNum).c_str()).str()); } } } else { @@ -789,12 +831,14 @@ void SocketCore::peekData(char* data, size_t& len) if(!secure_) { while((ret = recv(sockfd_, data, len, MSG_PEEK)) == -1 && SOCKET_ERRNO == A2_EINTR); + int errNum = SOCKET_ERRNO; if(ret == -1) { - if(A2_WOULDBLOCK(SOCKET_ERRNO)) { + if(A2_WOULDBLOCK(errNum)) { wantRead_ = true; ret = 0; } else { - throw DL_RETRY_EX(StringFormat(EX_SOCKET_PEEK, errorMsg()).str()); + throw DL_RETRY_EX(StringFormat(EX_SOCKET_PEEK, + errorMsg(errNum).c_str()).str()); } } } else { @@ -1133,20 +1177,23 @@ ssize_t SocketCore::writeData(const char* data, size_t len, WSAAPI_AUTO_DELETE resDeleter(res, freeaddrinfo); struct addrinfo* rp; ssize_t r = -1; + int errNum = 0; for(rp = res; rp; rp = rp->ai_next) { while((r = sendto(sockfd_, data, len, 0, rp->ai_addr, rp->ai_addrlen)) == -1 && A2_EINTR == SOCKET_ERRNO); + errNum = SOCKET_ERRNO; if(r == static_cast(len)) { break; } - if(r == -1 && A2_WOULDBLOCK(SOCKET_ERRNO)) { + if(r == -1 && A2_WOULDBLOCK(errNum)) { wantWrite_ = true; r = 0; break; } } if(r == -1) { - throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, errorMsg()).str()); + throw DL_ABORT_EX(StringFormat(EX_SOCKET_SEND, + errorMsg(errNum).c_str()).str()); } return r; } @@ -1163,12 +1210,14 @@ ssize_t SocketCore::readDataFrom(char* data, size_t len, ssize_t r; while((r = recvfrom(sockfd_, data, len, 0, addrp, &sockaddrlen)) == -1 && A2_EINTR == SOCKET_ERRNO); + int errNum = SOCKET_ERRNO; if(r == -1) { - if(A2_WOULDBLOCK(SOCKET_ERRNO)) { + if(A2_WOULDBLOCK(errNum)) { wantRead_ = true; r = 0; } else { - throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV, errorMsg()).str()); + throw DL_RETRY_EX(StringFormat(EX_SOCKET_RECV, + errorMsg(errNum).c_str()).str()); } } else { sender = util::getNumericNameInfo(addrp, sockaddrlen); @@ -1182,9 +1231,11 @@ std::string SocketCore::getSocketError() const int error; socklen_t optlen = sizeof(error); - if(getsockopt(sockfd_, SOL_SOCKET, SO_ERROR, (a2_sockopt_t) &error, &optlen) == -1) { + if(getsockopt(sockfd_, SOL_SOCKET, SO_ERROR, + (a2_sockopt_t) &error, &optlen) == -1) { + int errNum = SOCKET_ERRNO; throw DL_ABORT_EX(StringFormat("Failed to get socket error: %s", - errorMsg()).str()); + errorMsg(errNum).c_str()).str()); } if(error != 0) { return errorMsg(error); @@ -1243,7 +1294,9 @@ void getInterfaceAddress // First find interface in interface addresses struct ifaddrs* ifaddr = 0; if(getifaddrs(&ifaddr) == -1) { - logger->info(MSG_INTERFACE_NOT_FOUND, iface.c_str(), errorMsg()); + int errNum = SOCKET_ERRNO; + logger->info(MSG_INTERFACE_NOT_FOUND, + iface.c_str(), errorMsg(errNum).c_str()); } else { auto_delete ifaddrDeleter(ifaddr, freeifaddrs); for(struct ifaddrs* ifa = ifaddr; ifa; ifa = ifa->ifa_next) { diff --git a/src/message.h b/src/message.h index e04ab897..2022ea05 100644 --- a/src/message.h +++ b/src/message.h @@ -229,9 +229,8 @@ #define EX_FILE_OFFSET_OUT_OF_RANGE _("The offset is out of range, offset=%s") #define EX_NOT_DIRECTORY _("%s is not a directory.") #define EX_MAKE_DIR _("Failed to make the directory %s, cause: %s") -#define EX_SEGMENT_FILE_OPEN _("Failed to open the segment file %s, cause: %s") -#define EX_SEGMENT_FILE_WRITE _("Failed to write into the segment file %s, cause: %s") -#define EX_SEGMENT_FILE_READ _("Failed to read from the segment file %s, cause: %s") +#define EX_SEGMENT_FILE_WRITE "Failed to write into the segment file %s" +#define EX_SEGMENT_FILE_READ "Failed to read from the segment file %s" #define EX_SOCKET_OPEN _("Failed to open a socket, cause: %s") #define EX_SOCKET_SET_OPT _("Failed to set a socket option, cause: %s") diff --git a/src/util.cc b/src/util.cc index e5822b2d..53b0919c 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1128,10 +1128,13 @@ unsigned int alphaToNum(const std::string& alphabets) void mkdirs(const std::string& dirpath) { File dir(dirpath); - if(!dir.mkdirs() &&!dir.isDir()) { - throw DL_ABORT_EX - (StringFormat(EX_MAKE_DIR, dir.getPath().c_str(), - strerror(errno)).str()); + if(!dir.mkdirs()) { + int errNum = errno; + if(!dir.isDir()) { + throw DL_ABORT_EX + (StringFormat(EX_MAKE_DIR, dir.getPath().c_str(), + safeStrerror(errNum).c_str()).str()); + } } } @@ -1171,7 +1174,8 @@ void* allocateAlignedMemory(size_t alignment, size_t size) int res; if((res = posix_memalign(&buffer, alignment, size)) != 0) { throw FATAL_EXCEPTION - (StringFormat("Error in posix_memalign: %s", strerror(res)).str()); + (StringFormat("Error in posix_memalign: %s", + util::safeStrerror(res).c_str()).str()); } return buffer; } @@ -1498,6 +1502,20 @@ std::string encodeNonUtf8(const std::string& s) return util::isUtf8(s)?s:util::percentEncode(s); } +std::string makeString(const char* str) +{ + if(str) { + return str; + } else { + return A2STR::NIL; + } +} + +std::string safeStrerror(int errNum) +{ + return makeString(strerror(errNum)); +} + } // namespace util } // namespace aria2 diff --git a/src/util.h b/src/util.h index 8c47bf04..6982fa83 100644 --- a/src/util.h +++ b/src/util.h @@ -427,6 +427,14 @@ std::string createSafePath(const std::string& dir, const std::string& filename); std::string encodeNonUtf8(const std::string& s); +// Create string safely. If str is NULL, returns empty string. +// Otherwise, returns std::string(str). +std::string makeString(const char* str); + +// This function is basically the same with strerror(errNum) but when +// strerror returns NULL, this function returns empty string. +std::string safeStrerror(int errNum); + } // namespace util } // namespace aria2