Prechádzať zdrojové kódy

Add SessionConfig to store per Session config

sessionConfigSetKeepRunning() was removed and SessionConfig has
keepRunning member instead. Signal handlers are now all prepared in
MultiUrlRequestGroup object. Setting SessionConfig.useSignalHandler to
false will avoid signal handler setup.
Tatsuhiro Tsujikawa 12 rokov pred
rodič
commit
ebfc5f55e5

+ 0 - 15
src/Context.cc

@@ -34,7 +34,6 @@
 /* copyright --> */
 #include "Context.h"
 
-#include <signal.h>
 #include <unistd.h>
 #include <getopt.h>
 
@@ -223,20 +222,6 @@ Context::Context(bool standalone,
     std::string iface = op->get(PREF_INTERFACE);
     SocketCore::bindAddress(iface);
   }
-  sigset_t mask;
-#ifdef HAVE_SIGACTION
-  sigemptyset(&mask);
-#else // !HAVE_SIGACTION
-  mask = 0;
-#endif // !HAVE_SIGACTION
-#ifdef SIGPIPE
-  util::setGlobalSignalHandler(SIGPIPE, &mask, SIG_IGN, 0);
-#endif
-#ifdef SIGCHLD
-  // Avoid to create zombie process when forked child processes are
-  // died.
-  util::setGlobalSignalHandler(SIGCHLD, &mask, SIG_IGN, 0);
-#endif // SIGCHILD
   std::vector<SharedHandle<RequestGroup> > requestGroups;
   SharedHandle<UriListParser> uriListParser;
 #ifdef ENABLE_BITTORRENT

+ 1 - 2
src/KeepRunningCommand.cc

@@ -49,8 +49,7 @@ KeepRunningCommand::~KeepRunningCommand() {}
 
 bool KeepRunningCommand::execute()
 {
-  if(!e_->getRequestGroupMan()->getKeepRunning() ||
-     e_->isHaltRequested()) {
+  if(e_->isHaltRequested()) {
     return true;
   }
   e_->addCommand(this);

+ 49 - 20
src/MultiUrlRequestInfo.cc

@@ -112,8 +112,9 @@ MultiUrlRequestInfo::MultiUrlRequestInfo
   : option_(op),
     statCalc_(statCalc),
     summaryOut_(summaryOut),
-    uriListParser_(uriListParser)
+    uriListParser_(uriListParser),
     // TODO init mask_
+    useSignalHandler_(true)
 {
   requestGroups_.swap(requestGroups);
 }
@@ -238,27 +239,15 @@ int MultiUrlRequestInfo::prepare()
     if(uriListParser_) {
       e_->getRequestGroupMan()->setUriListParser(uriListParser_);
     }
-#ifdef HAVE_SIGACTION
-    sigemptyset(&mask_);
-    sigaddset(&mask_, SIGINT);
-    sigaddset(&mask_, SIGTERM);
-#ifdef SIGHUP
-    sigaddset(&mask_, SIGHUP);
-#endif // SIGHUP
-#else // !HAVE_SIGACTION
-    mask_ = 0;
-#endif // !HAVE_SIGACTION
-
-#ifdef SIGHUP
-    util::setGlobalSignalHandler(SIGHUP, &mask_, handler, 0);
-#endif // SIGHUP
-    util::setGlobalSignalHandler(SIGINT, &mask_, handler, 0);
-    util::setGlobalSignalHandler(SIGTERM, &mask_, handler, 0);
-
+    if(useSignalHandler_) {
+      setupSignalHandlers();
+    }
     e_->getRequestGroupMan()->getNetStat().downloadStart();
   } catch(RecoverableException& e) {
     SingletonHolder<Notifier>::clear();
-    resetSignalHandlers();
+    if(useSignalHandler_) {
+      resetSignalHandlers();
+    }
     return -1;
   }
   return 0;
@@ -319,10 +308,43 @@ error_code::Value MultiUrlRequestInfo::execute()
     A2_LOG_ERROR_EX(EX_EXCEPTION_CAUGHT, e);
   }
   error_code::Value returnValue = getResult();
-  resetSignalHandlers();
+  if(useSignalHandler_) {
+    resetSignalHandlers();
+  }
   return returnValue;
 }
 
+void MultiUrlRequestInfo::setupSignalHandlers()
+{
+#ifdef HAVE_SIGACTION
+    sigemptyset(&mask_);
+#else // !HAVE_SIGACTION
+    mask_ = 0;
+#endif // !HAVE_SIGACTION
+#ifdef SIGPIPE
+    util::setGlobalSignalHandler(SIGPIPE, &mask_, SIG_IGN, 0);
+#endif // SIGPIPE
+#ifdef SIGCHLD
+    // Avoid to create zombie process when forked child processes are
+    // died.
+    util::setGlobalSignalHandler(SIGCHLD, &mask_, SIG_IGN, 0);
+#endif // SIGCHILD
+
+#ifdef HAVE_SIGACTION
+    sigaddset(&mask_, SIGINT);
+    sigaddset(&mask_, SIGTERM);
+# ifdef SIGHUP
+    sigaddset(&mask_, SIGHUP);
+# endif // SIGHUP
+#endif // HAVE_SIGACTION
+
+#ifdef SIGHUP
+    util::setGlobalSignalHandler(SIGHUP, &mask_, handler, 0);
+#endif // SIGHUP
+    util::setGlobalSignalHandler(SIGINT, &mask_, handler, 0);
+    util::setGlobalSignalHandler(SIGTERM, &mask_, handler, 0);
+}
+
 void MultiUrlRequestInfo::resetSignalHandlers()
 {
 #ifdef HAVE_SIGACTION
@@ -333,6 +355,13 @@ void MultiUrlRequestInfo::resetSignalHandlers()
 #endif // SIGHUP
   util::setGlobalSignalHandler(SIGINT, &mask_, SIG_DFL, 0);
   util::setGlobalSignalHandler(SIGTERM, &mask_, SIG_DFL, 0);
+
+#ifdef SIGCHLD
+    util::setGlobalSignalHandler(SIGCHLD, &mask_, SIG_DFL, 0);
+#endif // SIGCHILD
+#ifdef SIGPIPE
+    util::setGlobalSignalHandler(SIGPIPE, &mask_, SIG_DFL, 0);
+#endif // SIGPIPE
 }
 
 const SharedHandle<DownloadEngine>&

+ 9 - 0
src/MultiUrlRequestInfo.h

@@ -70,7 +70,10 @@ private:
 
   sigset_t mask_;
 
+  bool useSignalHandler_;
+
   void printMessageForContinue();
+  void setupSignalHandlers();
   void resetSignalHandlers();
 public:
   /*
@@ -105,6 +108,12 @@ public:
   error_code::Value getResult();
 
   const SharedHandle<DownloadEngine>& getDownloadEngine() const;
+
+  // Signal handlers are not prepared if false is given.
+  void setUseSignalHandler(bool useSignalHandler)
+  {
+    useSignalHandler_ = useSignalHandler;
+  }
 };
 
 } // namespace aria2

+ 14 - 11
src/aria2api.cc

@@ -68,6 +68,11 @@ Session::Session(const KeyVals& options)
 Session::~Session()
 {}
 
+SessionConfig::SessionConfig()
+  : keepRunning(false),
+    useSignalHandler(true)
+{}
+
 namespace {
 Platform* platform = 0;
 } // namespace
@@ -91,7 +96,7 @@ int libraryDeinit()
   return 0;
 }
 
-Session* sessionNew(const KeyVals& options)
+Session* sessionNew(const KeyVals& options, const SessionConfig& config)
 {
   int rv;
   Session* session;
@@ -101,6 +106,9 @@ Session* sessionNew(const KeyVals& options)
     return 0;
   }
   if(session->context->reqinfo) {
+    if(!config.useSignalHandler) {
+      session->context->reqinfo->setUseSignalHandler(false);
+    }
     rv = session->context->reqinfo->prepare();
     if(rv != 0) {
       delete session;
@@ -108,9 +116,11 @@ Session* sessionNew(const KeyVals& options)
     }
     const SharedHandle<DownloadEngine>& e =
       session->context->reqinfo->getDownloadEngine();
-    // Add command to make aria2 keep event polling if
-    // sessionConfigSetKeepRunning is set to true.
-    e->addCommand(new KeepRunningCommand(e->newCUID(), e.get()));
+    if(config.keepRunning) {
+      e->getRequestGroupMan()->setKeepRunning(true);
+      // Add command to make aria2 keep event polling
+      e->addCommand(new KeepRunningCommand(e->newCUID(), e.get()));
+    }
   } else {
     delete session;
     session = 0;
@@ -125,13 +135,6 @@ int sessionFinal(Session* session)
   return rv;
 }
 
-int sessionConfigSetKeepRunning(Session* session, bool flag)
-{
-  session->context->reqinfo->getDownloadEngine()->getRequestGroupMan()
-    ->setKeepRunning(flag);
-  return 0;
-}
-
 int run(Session* session, RUN_MODE mode)
 {
   const SharedHandle<DownloadEngine>& e =

+ 25 - 8
src/includes/aria2/aria2.h

@@ -74,6 +74,30 @@ typedef uint64_t A2Gid;
 // type of Key/Value pairs
 typedef std::vector<std::pair<std::string, std::string> > KeyVals;
 
+struct SessionConfig {
+  // The constructor fills default values for all members.
+  SessionConfig();
+  // If the |keepRunning| member is true, run(session, RUN_ONCE) will
+  // return 1 even if there are no download to perform. The behavior
+  // is very similar to RPC server, except that this option does not
+  // enable RPC functionality. To stop aria2, use shutdown() function.
+  // The default value is false.
+  bool keepRunning;
+  // If the |useSignalHandler| is true, the library setups following
+  // signal handlers in sessionNew(). These signal handlers are
+  // removed in sessionFinal(). The default value is true. If the
+  // application sets this member to false, it must handle these
+  // signals and ensure that run() is repeatedly called until it
+  // returns 0 and sessionFinal() is called after that. Failing these
+  // steps will lead to not saving .aria2 control file and no session
+  // serialization.
+  //
+  // SIGPIPE, SIGCHLD: ignored
+  // SIGHUP, SIGTERM: handled like shutdown(session, true) is called.
+  // SIGINT: handled like shutdown(session, false) is called.
+  bool useSignalHandler;
+};
+
 // Creates new Session object using the |options| as additional
 // parameters. The |options| is treated as if they are specified in
 // command-line to aria2c(1). This function returns the pointer to the
@@ -81,7 +105,7 @@ typedef std::vector<std::pair<std::string, std::string> > KeyVals;
 //
 // Please note that only one Session object can be created per
 // process.
-Session* sessionNew(const KeyVals& options);
+Session* sessionNew(const KeyVals& options, const SessionConfig& config);
 
 // Performs post-download action, including saving sessions etc and
 // destroys the |session| object, releasing the allocated resources
@@ -94,13 +118,6 @@ enum RUN_MODE {
   RUN_ONCE
 };
 
-// If the |flag| is true, run(session, RUN_ONCE) will return 1 even if
-// there are no download to perform. The behavior is very similar to
-// RPC server, except that this option does not enable RPC
-// functionality. To stop aria2, use shutdown() function.  This
-// function returns 0 if it succeeds, or -1.
-int sessionConfigSetKeepRunning(Session* session, bool flag);
-
 // Performs event polling and actions for them. If the |mode| is
 // RUN_DEFAULT, this function returns when no downloads are left to be
 // processed. In this case, this function returns 0.