2007-12-07 Tatsuhiro Tsujikawa <tujikawa at rednoah com>

Fixed the bug#1845750; CTRL+C does not stop torrent.
	aria2 repeatedly sends stopped request when tracker returns error code.
	* src/AnnounceList.cc
	* test/AnnounceListTest.cc
	* src/AnnounceTier.h

	Added a message when ctrl-c is hit.
	Now second ctrl-c is also handled in signal handler.
	* src/RequestGroupMan.{h, cc}
	* src/RequestGroup.{h, cc}
	* src/MultiUrlRequestInfo.cc
	* src/DownloadEngine.cc
	* src/TrackerWatcherCommand.cc
pull/1/head
Tatsuhiro Tsujikawa 2007-12-07 13:33:59 +00:00
parent 3bb307b518
commit bb4bff2c2a
11 changed files with 112 additions and 6 deletions

View File

@ -1,3 +1,19 @@
2007-12-07 Tatsuhiro Tsujikawa <tujikawa at rednoah com>
Fixed the bug#1845750; CTRL+C does not stop torrent.
aria2 repeatedly sends stopped request when tracker returns error code.
* src/AnnounceList.cc
* test/AnnounceListTest.cc
* src/AnnounceTier.h
Added a message when ctrl-c is hit.
Now second ctrl-c is also handled in signal handler.
* src/RequestGroupMan.{h, cc}
* src/RequestGroup.{h, cc}
* src/MultiUrlRequestInfo.cc
* src/DownloadEngine.cc
* src/TrackerWatcherCommand.cc
2007-12-06 Tatsuhiro Tsujikawa <tujikawa at rednoah dot com>
Code cleanup

View File

@ -107,6 +107,8 @@ void AnnounceList::announceFailure() {
if(currentTrackerInitialized) {
currentTracker++;
if(currentTracker == (*currentTier)->urls.end()) {
// force next event
(*currentTier)->nextEventIfAfterStarted();
currentTier++;
if(currentTier == tiers.end()) {
currentTrackerInitialized = false;

View File

@ -72,6 +72,20 @@ public:
break;
}
}
void nextEventIfAfterStarted()
{
switch(event) {
case STOPPED:
event = HALTED;
break;
case COMPLETED:
event = SEEDING;
break;
default:
break;
}
}
};
typedef SharedHandle<AnnounceTier> AnnounceTierHandle;

View File

@ -50,7 +50,12 @@
#include <fcntl.h>
#include <signal.h>
volatile sig_atomic_t globalHaltRequested;
// 0 ... running
// 1 ... stop signal detected
// 2 ... stop signal processed by DownloadEngine
// 3 ... 2nd stop signal(force shutdown) detected
// 4 ... 2nd stop signal processed by DownloadEngine
volatile sig_atomic_t globalHaltRequested = 0;
SocketEntry::SocketEntry(const SocketHandle& socket,
Command* command,
@ -276,10 +281,15 @@ void DownloadEngine::onEndOfRun()
void DownloadEngine::afterEachIteration()
{
if(globalHaltRequested) {
globalHaltRequested = false;
if(globalHaltRequested == 1) {
logger->notice(_("Shutdown sequence commencing... Press Ctrl-C again for emergency shutdown."));
_haltRequested = true;
_requestGroupMan->halt();
globalHaltRequested = 2;
} else if(globalHaltRequested == 3) {
logger->notice(_("Emergency shutdown sequence commencing..."));
_requestGroupMan->forceHalt();
globalHaltRequested = 4;
}
}

View File

@ -53,7 +53,11 @@
extern volatile sig_atomic_t globalHaltRequested;
static void handler(int signal) {
globalHaltRequested = true;
if(globalHaltRequested == 0) {
globalHaltRequested = 1;
} else if(globalHaltRequested == 2) {
globalHaltRequested = 3;
}
}
MultiUrlRequestInfo::MultiUrlRequestInfo(const RequestGroups& requestGroups, Option* op):
@ -94,8 +98,8 @@ void MultiUrlRequestInfo::execute()
// This is done every 1 second. At the same time, it removes finished/error
// RequestGroup from DownloadEngine.
Util::setGlobalSignalHandler(SIGINT, handler, SA_RESETHAND);
Util::setGlobalSignalHandler(SIGTERM, handler, SA_RESETHAND);
Util::setGlobalSignalHandler(SIGINT, handler, 0);
Util::setGlobalSignalHandler(SIGTERM, handler, 0);
e->run();

View File

@ -95,6 +95,7 @@ RequestGroup::RequestGroup(const Option* option,
_dependency(0),
_preLocalFileCheckEnabled(true),
_haltRequested(false),
_forceHaltRequested(false),
_option(option),
_logger(LogFactory::getInstance())
{
@ -540,6 +541,12 @@ void RequestGroup::setHaltRequested(bool f)
#endif // ENABLE_BITTORRENT
}
void RequestGroup::setForceHaltRequested(bool f)
{
setHaltRequested(f);
_forceHaltRequested = f;
}
void RequestGroup::releaseRuntimeResource()
{
#ifdef ENABLE_BITTORRENT

View File

@ -109,6 +109,8 @@ private:
bool _haltRequested;
bool _forceHaltRequested;
PreDownloadHandlers _preDownloadHandlers;
PostDownloadHandlers _postDownloadHandlers;
@ -262,11 +264,18 @@ public:
void setHaltRequested(bool f);
void setForceHaltRequested(bool f);
bool isHaltRequested() const
{
return _haltRequested;
}
bool isForceHaltRequested() const
{
return _forceHaltRequested;
}
void dependsOn(const DependencyHandle& dep);
bool isDependencyResolved();

View File

@ -287,6 +287,14 @@ void RequestGroupMan::halt()
}
}
void RequestGroupMan::forceHalt()
{
for(RequestGroups::const_iterator itr = _requestGroups.begin();
itr != _requestGroups.end(); ++itr) {
(*itr)->setForceHaltRequested(true);
}
}
TransferStat RequestGroupMan::calculateStat()
{
return accumulate(_requestGroups.begin(), _requestGroups.end(), TransferStat(),

View File

@ -72,6 +72,8 @@ public:
void halt();
void forceHalt();
Commands getInitialCommands(DownloadEngine* e);
void removeStoppedGroup();

View File

@ -64,6 +64,17 @@ TrackerWatcherCommand::~TrackerWatcherCommand() {}
bool TrackerWatcherCommand::execute() {
if(_requestGroup->isForceHaltRequested()) {
if(_trackerRequestGroup.isNull()) {
return true;
} else if(_trackerRequestGroup->getNumCommand() == 0 ||
_trackerRequestGroup->downloadFinished()) {
return true;
} else {
_trackerRequestGroup->setForceHaltRequested(true);
return false;
}
}
if(btAnnounce->noMoreAnnounce()) {
logger->debug("no more announce");
return true;

View File

@ -12,6 +12,8 @@ class AnnounceListTest:public CppUnit::TestFixture {
CPPUNIT_TEST(testMultiElementList);
CPPUNIT_TEST(testSingleAndMulti);
CPPUNIT_TEST(testNoGroup);
CPPUNIT_TEST(testEvent);
CPPUNIT_TEST(testNextEventIfAfterStarted);
CPPUNIT_TEST(testCountStoppedAllowedTier);
CPPUNIT_TEST(testCountCompletedAllowedTier);
CPPUNIT_TEST(testMoveToStoppedAllowedTier);
@ -28,6 +30,7 @@ public:
void testSingleAndMulti();
void testNoGroup();
void testEvent();
void testNextEventIfAfterStarted();
void testCountStoppedAllowedTier();
void testCountCompletedAllowedTier();
void testMoveToStoppedAllowedTier();
@ -150,6 +153,26 @@ void AnnounceListTest::testNoGroup() {
CPPUNIT_ASSERT(announceList.countTier() == 0);
}
void AnnounceListTest::testNextEventIfAfterStarted() {
string peersString = "ll8:tracker1ee";
Dictionary* announces = (Dictionary*)MetaFileUtil::bdecoding(peersString.c_str(), peersString.size());
// ANNOUNCE_LIST
// [ [ tracker1 ] ]
AnnounceList announceList(announces);
announceList.setEvent(AnnounceTier::STOPPED);
announceList.announceFailure();
announceList.resetTier();
CPPUNIT_ASSERT_EQUAL(string(""), announceList.getEventString());
CPPUNIT_ASSERT_EQUAL(AnnounceTier::HALTED, announceList.getEvent());
announceList.setEvent(AnnounceTier::COMPLETED);
announceList.announceFailure();
announceList.resetTier();
CPPUNIT_ASSERT_EQUAL(string(""), announceList.getEventString());
CPPUNIT_ASSERT_EQUAL(AnnounceTier::SEEDING, announceList.getEvent());
}
void AnnounceListTest::testEvent() {
string peersString = "ll8:tracker1el8:tracker2el8:tracker3ee";
Dictionary* announces = (Dictionary*)MetaFileUtil::bdecoding(peersString.c_str(), peersString.size());