]> granicus.if.org Git - icinga2/commitdiff
Make rlimits configurable by adding three variables: RLimitFiles, RLimitProcesses... 5373/head
authorGunnar Beutner <gunnar.beutner@icinga.com>
Wed, 21 Jun 2017 09:36:14 +0000 (11:36 +0200)
committerMichael Friedrich <michael.friedrich@icinga.com>
Fri, 23 Jun 2017 10:42:12 +0000 (12:42 +0200)
refs #5367

doc/17-language-reference.md
icinga-app/icinga.cpp
lib/base/application.cpp
lib/base/application.hpp

index adc20520f1f58d30a82c2ccf9bc97790d395c398..989d9ae484931f668b8f0154f2c1276ce2c8e347 100644 (file)
@@ -368,6 +368,8 @@ Global constants can be set using the `const` keyword:
 Once defined a constant can be accessed from any file. Constants cannot be changed
 once they are set.
 
+### <a id="icinga-constants"></a> Icinga 2 Specific Constants
+
 Icinga 2 provides a number of special global constants. Some of them can be overridden using the `--define` command line parameter:
 
 Variable            |Description
@@ -383,8 +385,6 @@ ObjectsPath         |**Read-write.** Contains the path of the Icinga 2 objects f
 PidPath             |**Read-write.** Contains the path of the Icinga 2 PID file. Defaults to RunDir + "/icinga2/icinga2.pid".
 Vars                |**Read-write.** Contains a dictionary with global custom attributes. Not set by default.
 NodeName            |**Read-write.** Contains the cluster node name. Set to the local hostname by default.
-EventEngine         |**Read-write.** The name of the socket event engine, can be "poll" or "epoll". The epoll interface is only supported on Linux.
-AttachDebugger      |**Read-write.** Whether to attach a debugger when Icinga 2 crashes. Defaults to false.
 RunAsUser           |**Read-write.** Defines the user the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
 RunAsGroup          |**Read-write.** Defines the group the Icinga 2 daemon is running as. Used in the `init.conf` configuration file.
 PlatformName        |**Read-only.** The name of the operating system, e.g. "Ubuntu".
@@ -395,6 +395,17 @@ BuildCompilerName   |**Read-only.** The name of the compiler Icinga was built wi
 BuildCompilerVersion|**Read-only.** The version of the compiler Icinga was built with, e.g. "7.3.0.7030031".
 BuildHostName       |**Read-only.** The name of the host Icinga was built on, e.g. "acheron".
 
+
+Advanced runtime constants. Please only use them if advised by support or developers.
+
+Variable            |Description
+--------------------|-------------------
+EventEngine         |**Read-write.** The name of the socket event engine, can be `poll` or `epoll`. The epoll interface is only supported on Linux.
+AttachDebugger      |**Read-write.** Whether to attach a debugger when Icinga 2 crashes. Defaults to `false`.
+RLimitFiles         |**Read-write.** Defines the resource limit for RLIMIT_NOFILE that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Used in the `init.conf` configuration file.
+RLimitProcesses     |**Read-write.** Defines the resource limit for RLIMIT_NPROC that should be set at start-up. Value cannot be set lower than the default `16 * 1024`. 0 disables the setting. Used in the `init.conf` configuration file.
+RLimitStack         |**Read-write.** Defines the resource limit for RLIMIT_STACK that should be set at start-up. Value cannot be set lower than the default `256 * 1024`. 0 disables the setting. Used in the `init.conf` configuration file.
+
 ## <a id="apply"></a> Apply
 
 The `apply` keyword can be used to create new objects which are associated with
index f264db96c858765e72815f1e80d71a861d3f5870..2007e8c589a663889ebdd1bf7137a7010562bc15 100644 (file)
@@ -113,9 +113,6 @@ int Main(void)
 
        Application::SetStartTime(Utility::GetTime());
 
-       if (!autocomplete)
-               Application::SetResourceLimits();
-
        /* Set thread title. */
        Utility::SetThreadName("Main Thread", false);
 
@@ -152,6 +149,11 @@ int Main(void)
        Application::DeclareZonesDir(Application::GetSysconfDir() + "/icinga2/zones.d");
        Application::DeclareRunAsUser(ICINGA_USER);
        Application::DeclareRunAsGroup(ICINGA_GROUP);
+#ifdef __linux__
+       Application::DeclareRLimitFiles(Application::GetDefaultRLimitFiles());
+       Application::DeclareRLimitProcesses(Application::GetDefaultRLimitProcesses());
+       Application::DeclareRLimitStack(Application::GetDefaultRLimitStack());
+#endif /* __linux__ */
        Application::DeclareConcurrency(boost::thread::hardware_concurrency());
 
        ScriptGlobal::Set("AttachDebugger", false);
@@ -166,6 +168,28 @@ int Main(void)
        ScriptGlobal::Set("BuildCompilerName", ICINGA_BUILD_COMPILER_NAME);
        ScriptGlobal::Set("BuildCompilerVersion", ICINGA_BUILD_COMPILER_VERSION);
 
+       String initconfig = Application::GetSysconfDir() + "/icinga2/init.conf";
+
+       if (Utility::PathExists(initconfig)) {
+               Expression *expression;
+               try {
+                       expression = ConfigCompiler::CompileFile(initconfig);
+
+                       ScriptFrame frame;
+                       expression->Evaluate(frame);
+               } catch (const std::exception& ex) {
+                       delete expression;
+
+                       Log(LogCritical, "config", DiagnosticInformation(ex));
+                       return EXIT_FAILURE;
+               }
+
+               delete expression;
+       }
+
+       if (!autocomplete)
+               Application::SetResourceLimits();
+
        LogSeverity logLevel = Logger::GetConsoleLogSeverity();
        Logger::SetConsoleLogSeverity(LogWarning);
 
@@ -209,25 +233,6 @@ int Main(void)
                return EXIT_FAILURE;
        }
 
-       String initconfig = Application::GetSysconfDir() + "/icinga2/init.conf";
-
-       if (Utility::PathExists(initconfig)) {
-               Expression *expression;
-               try {
-                       expression = ConfigCompiler::CompileFile(initconfig);
-
-                       ScriptFrame frame;
-                       expression->Evaluate(frame);
-               } catch (const std::exception& ex) {
-                       delete expression;
-
-                       Log(LogCritical, "config", DiagnosticInformation(ex));
-                       return EXIT_FAILURE;
-               }
-
-               delete expression;
-       }
-
 #ifndef _WIN32
        if (vm.count("color")) {
                Console::SetType(std::cout, Console_VT100);
index b6bb028617fb49e04cc32c41677cf18c3e749804..c1c2692c82160a74b22f5ddebe7f15261cb87140 100644 (file)
@@ -180,24 +180,44 @@ void Application::SetResourceLimits(void)
        rlimit rl;
 
 #      ifdef RLIMIT_NOFILE
-       rl.rlim_cur = 16 * 1024;
-       rl.rlim_max = rl.rlim_cur;
+       rlim_t fileLimit = GetRLimitFiles();
 
-       if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
-               Log(LogNotice, "Application", "Could not adjust resource limit for open file handles (RLIMIT_NOFILE)");
+       if (fileLimit != 0) {
+               if (fileLimit < GetDefaultRLimitFiles()) {
+                       Log(LogWarning, "Application")
+                           << "The user-specified value for RLimitFiles cannot be smaller than the default value (" << GetDefaultRLimitFiles() << "). Using the default value instead.";
+                       fileLimit = GetDefaultRLimitFiles();
+               }
+
+               rl.rlim_cur = fileLimit;
+               rl.rlim_max = rl.rlim_cur;
+
+               if (setrlimit(RLIMIT_NOFILE, &rl) < 0)
+                       Log(LogNotice, "Application", "Could not adjust resource limit for open file handles (RLIMIT_NOFILE)");
 #      else /* RLIMIT_NOFILE */
-       Log(LogNotice, "Application", "System does not support adjusting the resource limit for open file handles (RLIMIT_NOFILE)");
+               Log(LogNotice, "Application", "System does not support adjusting the resource limit for open file handles (RLIMIT_NOFILE)");
 #      endif /* RLIMIT_NOFILE */
+       }
 
 #      ifdef RLIMIT_NPROC
-       rl.rlim_cur = 16 * 1024;
-       rl.rlim_max = rl.rlim_cur;
+       rlim_t processLimit = GetRLimitProcesses();
+
+       if (processLimit != 0) {
+               if (processLimit < GetDefaultRLimitProcesses()) {
+                       Log(LogWarning, "Application")
+                           << "The user-specified value for RLimitProcesses cannot be smaller than the default value (" << GetDefaultRLimitProcesses() << "). Using the default value instead.";
+                       processLimit = GetDefaultRLimitProcesses();
+               }
 
-       if (setrlimit(RLIMIT_NPROC, &rl) < 0)
-               Log(LogNotice, "Application", "Could not adjust resource limit for number of processes (RLIMIT_NPROC)");
+               rl.rlim_cur = processLimit;
+               rl.rlim_max = rl.rlim_cur;
+
+               if (setrlimit(RLIMIT_NPROC, &rl) < 0)
+                       Log(LogNotice, "Application", "Could not adjust resource limit for number of processes (RLIMIT_NPROC)");
 #      else /* RLIMIT_NPROC */
-       Log(LogNotice, "Application", "System does not support adjusting the resource limit for number of processes (RLIMIT_NPROC)");
+               Log(LogNotice, "Application", "System does not support adjusting the resource limit for number of processes (RLIMIT_NPROC)");
 #      endif /* RLIMIT_NPROC */
+       }
 
 #      ifdef RLIMIT_STACK
        int argc = Application::GetArgC();
@@ -216,41 +236,53 @@ void Application::SetResourceLimits(void)
                rl.rlim_max = RLIM_INFINITY;
        }
 
-       if (set_stack_rlimit)
-               rl.rlim_cur = 256 * 1024;
-       else
-               rl.rlim_cur = rl.rlim_max;
+       rlim_t stackLimit;
 
-       if (setrlimit(RLIMIT_STACK, &rl) < 0)
-               Log(LogNotice, "Application", "Could not adjust resource limit for stack size (RLIMIT_STACK)");
-       else if (set_stack_rlimit) {
-               char **new_argv = static_cast<char **>(malloc(sizeof(char *) * (argc + 2)));
+       stackLimit = GetRLimitStack();
 
-               if (!new_argv) {
-                       perror("malloc");
-                       Exit(EXIT_FAILURE);
+       if (stackLimit != 0) {
+               if (stackLimit < GetDefaultRLimitStack()) {
+                       Log(LogWarning, "Application")
+                           << "The user-specified value for RLimitStack cannot be smaller than the default value (" << GetDefaultRLimitStack() << "). Using the default value instead.";
+                       stackLimit = GetDefaultRLimitStack();
                }
 
-               new_argv[0] = argv[0];
-               new_argv[1] = strdup("--no-stack-rlimit");
+               if (set_stack_rlimit)
+                       rl.rlim_cur = stackLimit;
+               else
+                       rl.rlim_cur = rl.rlim_max;
 
-               if (!new_argv[1]) {
-                       perror("strdup");
-                       exit(1);
-               }
+               if (setrlimit(RLIMIT_STACK, &rl) < 0)
+                       Log(LogNotice, "Application", "Could not adjust resource limit for stack size (RLIMIT_STACK)");
+               else if (set_stack_rlimit) {
+                       char **new_argv = static_cast<char **>(malloc(sizeof(char *) * (argc + 2)));
 
-               for (int i = 1; i < argc; i++)
-                       new_argv[i + 1] = argv[i];
+                       if (!new_argv) {
+                               perror("malloc");
+                               Exit(EXIT_FAILURE);
+                       }
 
-               new_argv[argc + 1] = NULL;
+                       new_argv[0] = argv[0];
+                       new_argv[1] = strdup("--no-stack-rlimit");
 
-               (void) execvp(new_argv[0], new_argv);
-               perror("execvp");
-               _exit(EXIT_FAILURE);
-       }
+                       if (!new_argv[1]) {
+                               perror("strdup");
+                               exit(1);
+                       }
+
+                       for (int i = 1; i < argc; i++)
+                               new_argv[i + 1] = argv[i];
+
+                       new_argv[argc + 1] = NULL;
+
+                       (void) execvp(new_argv[0], new_argv);
+                       perror("execvp");
+                       _exit(EXIT_FAILURE);
+               }
 #      else /* RLIMIT_STACK */
-       Log(LogNotice, "Application", "System does not support adjusting the resource limit for stack size (RLIMIT_STACK)");
+               Log(LogNotice, "Application", "System does not support adjusting the resource limit for stack size (RLIMIT_STACK)");
 #      endif /* RLIMIT_STACK */
+       }
 #endif /* __linux__ */
 }
 
@@ -1331,6 +1363,95 @@ String Application::GetRunAsGroup(void)
        return ScriptGlobal::Get("RunAsGroup");
 }
 
+/**
+ * Sets the name of the group.
+ *
+ * @param path The new group name.
+ */
+void Application::DeclareRunAsGroup(const String& group)
+{
+       if (!ScriptGlobal::Exists("RunAsGroup"))
+               ScriptGlobal::Set("RunAsGroup", group);
+}
+
+/**
+ * Retrieves the file rlimit.
+ *
+ * @returns The limit.
+ */
+int Application::GetRLimitFiles(void)
+{
+       return ScriptGlobal::Get("RLimitFiles");
+}
+
+int Application::GetDefaultRLimitFiles(void)
+{
+       return 16 * 1024;
+}
+
+/**
+ * Sets the file rlimit.
+ *
+ * @param path The new file rlimit.
+ */
+void Application::DeclareRLimitFiles(int limit)
+{
+       if (!ScriptGlobal::Exists("RLimitFiles"))
+               ScriptGlobal::Set("RLimitFiles", limit);
+}
+
+/**
+ * Retrieves the process rlimit.
+ *
+ * @returns The limit.
+ */
+int Application::GetRLimitProcesses(void)
+{
+       return ScriptGlobal::Get("RLimitProcesses");
+}
+
+int Application::GetDefaultRLimitProcesses(void)
+{
+       return 16 * 1024;
+}
+
+/**
+ * Sets the process rlimit.
+ *
+ * @param path The new process rlimit.
+ */
+void Application::DeclareRLimitProcesses(int limit)
+{
+       if (!ScriptGlobal::Exists("RLimitProcesses"))
+               ScriptGlobal::Set("RLimitProcesses", limit);
+}
+
+/**
+ * Retrieves the stack rlimit.
+ *
+ * @returns The limit.
+ */
+int Application::GetRLimitStack(void)
+{
+       return ScriptGlobal::Get("RLimitStack");
+}
+
+int Application::GetDefaultRLimitStack(void)
+{
+       return 256 * 1024;
+}
+
+/**
+ * Sets the stack rlimit.
+ *
+ * @param path The new stack rlimit.
+ */
+void Application::DeclareRLimitStack(int limit)
+{
+       if (!ScriptGlobal::Exists("RLimitStack"))
+               ScriptGlobal::Set("RLimitStack", limit);
+}
+
 /**
  * Sets the concurrency level.
  *
@@ -1353,17 +1474,6 @@ int Application::GetConcurrency(void)
        return ScriptGlobal::Get("Concurrency", &defaultConcurrency);
 }
 
-/**
- * Sets the name of the group.
- *
- * @param path The new group name.
- */
-void Application::DeclareRunAsGroup(const String& group)
-{
-       if (!ScriptGlobal::Exists("RunAsGroup"))
-               ScriptGlobal::Set("RunAsGroup", group);
-}
-
 /**
  * Returns the global thread pool.
  *
index 4009a68435d68dc39961a27d68efb15d64ea76ee..5c1469e12ab4974bb201dcb0a030b2488d7e2331 100644 (file)
@@ -126,6 +126,18 @@ public:
        static String GetRunAsGroup(void);
        static void DeclareRunAsGroup(const String& group);
 
+       static int GetRLimitFiles(void);
+       static int GetDefaultRLimitFiles(void);
+       static void DeclareRLimitFiles(int limit);
+
+       static int GetRLimitProcesses(void);
+       static int GetDefaultRLimitProcesses(void);
+       static void DeclareRLimitProcesses(int limit);
+
+       static int GetRLimitStack(void);
+       static int GetDefaultRLimitStack(void);
+       static void DeclareRLimitStack(int limit);
+
        static int GetConcurrency(void);
        static void DeclareConcurrency(int ncpus);