stdcxx-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From se...@apache.org
Subject svn commit: r443135 - in /incubator/stdcxx/trunk/util: cmdopt.cpp cmdopt.h exec.cpp
Date Wed, 13 Sep 2006 21:39:22 GMT
Author: sebor
Date: Wed Sep 13 14:39:22 2006
New Revision: 443135

URL: http://svn.apache.org/viewvc?view=rev&rev=443135
Log:
2006-09-13  Andrew Black  <ablack@roguewave.com>

	* cmdopt.h (unistd.h) [!_WIN32 && !_WIN64]: Include.
	(sys/resource.h) [_XOPEN_UNIX]: Include.
	(rw_rlim_t, struct rw_rlimit) [!_XOPEN_UNIX]: Define placeholder
	type/struct for rlim_t and struct rlimit respectively.
	(rw_rlimit, limit_set): Define.
	(child_limits): Declare.
	* cmdopt.cpp (sys/resource.h) [!_WIN32 && !_WIN64 && _XOPEN_UNIX]:
	Include.
	(RLIM_INFINITY, RLIM_SAVED_CUR, RLIM_SAVED_MAX): Define if not defined.
	(child_limits): Define/initialize.
	(usage_text): Document --ulimit switch.
	(parse_limit_opts): Define helper function for parsing --rlimit option
	borrowed in part from _rw_setopt_ulimit in tests/src/driver.cpp.
	(eval_options): Define opt_ulimit character string, use with
	parse_limit_opts to handle --ulimit command line switch.
	* exec.cpp (sys/resource.h) [!_WIN32 && !_WIN64 && _XOPEN_UNIX]:
	Include.
	(LIMIT) [!_WIN32 && !_WIN64 && _XOPEN_UNIX]: Define helper macro for...
	(limit_process) [!_WIN32 && !_WIN64 && _XOPEN_UNIX]: ... New helper
	function to set resource limits, based on the values in child_limits
	borrowed in part from _rw_setopt_ulimit in tests/src/driver.cpp.
	(exec_file) [!_WIN32 && !_WIN64 && _XOPEN_UNIX]: Call above prior to
	execv.

Modified:
    incubator/stdcxx/trunk/util/cmdopt.cpp
    incubator/stdcxx/trunk/util/cmdopt.h
    incubator/stdcxx/trunk/util/exec.cpp

Modified: incubator/stdcxx/trunk/util/cmdopt.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/cmdopt.cpp?view=diff&rev=443135&r1=443134&r2=443135
==============================================================================
--- incubator/stdcxx/trunk/util/cmdopt.cpp (original)
+++ incubator/stdcxx/trunk/util/cmdopt.cpp Wed Sep 13 14:39:22 2006
@@ -37,6 +37,11 @@
 #include <string.h> /* for str* */
 #if !defined (_WIN32) && !defined (_WIN64)
 #  include <unistd.h> /* for sleep */
+
+#  if defined (_XOPEN_UNIX)
+#    include <sys/resource.h> /* for struct rlimit, RLIMIT_CORE, ... */
+#  endif
+
 #else
 #  include <windows.h> /* for Sleep */
 #endif   /* _WIN{32,64} */
@@ -66,6 +71,28 @@
 const size_t exe_suffix_len = 4; /* strlen(".exe") == 4 */
 #endif
 
+#ifndef RLIM_INFINITY
+#  define RLIM_INFINITY -1
+#endif /* RLIM_INFINITY */
+
+#ifndef RLIM_SAVED_CUR
+#  define RLIM_SAVED_CUR RLIM_INFINITY
+#endif   /* RLIM_SAVED_CUR */
+
+#ifndef RLIM_SAVED_MAX
+#  define RLIM_SAVED_MAX RLIM_INFINITY
+#endif   /* RLIM_SAVED_MAX */
+struct limit_set child_limits = {
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX },
+    { RLIM_SAVED_CUR, RLIM_SAVED_MAX }
+};
+
 static const char
 usage_text[] = {
     "Usage: %s [OPTIONS] [targets]\n"
@@ -91,12 +118,39 @@
     "    --sleep=sec  Sleep for the specified number of seconds.\n"
     "    --signal=sig Send itself the specified signal.\n"
     "    --ignore=sig Ignore the specified signal.\n"
+    "    --ulimit=lim Set child process usage limits (see below).\n"
     "\n"
     "  All short (single dash) options must be specified seperately.\n"
     "  If a short option takes a value, it may either be provided like\n"
     "  '-sval' or '-s val'.\n"
     "  If a long option take a value, it may either be provided like\n"
     "  '--option=value' or '--option value'.\n"
+    "\n"
+    "  --ulimit sets limits on how much of a given resource or resorces\n"
+    "  child processes are allowed to utilize.  These limits take on two\n"
+    "  forms, 'soft' and 'hard' limits.  Options are specified in the form\n"
+    "  'resource:limit', where resource is a resource named below, and and\n"
+    "  limit is a number, with value specifing the limit for the named\n"
+    "  resource.  If multiple limits are to be set, they can be specified\n"
+    "  either in multiple instances of the --ulimit switch, or by specifying\n"
+    "  additional limits in the same call by seperating the pairs with\n"
+    "  commas.  'Soft' limits are specified by providing the resource name\n"
+    "  in lowercase letters, while 'hard' limits are specified by providing\n"
+    "  the resource name in uppercase letters.  To set both limits, specify\n"
+    "  the resource name in title case.\n"
+    "\n"
+    "  --ulimit modes:\n"
+    "    core   Maximum size of core file, in bytes.\n"
+    "    cpu    Maximum CPU time, in seconds.\n"
+    "    data   Maximum data segment size, in bytes.\n"
+    "    fsize  Maximum size of generated files, in bytes.\n"
+    "    nofile Maximum number of open file descriptors.\n"
+    "    stack  Maximum size of initial thread's stack, in bytes.\n"
+    "    as     Maximum size of available memory, in bytes.\n"
+    "\n"
+    "  Note: Some operating systems lack support for some or all of the\n"
+    "  ulimit modes.  If a system is unable to limit a given property, a\n"
+    "  warning message will be produced.\n"
 };
 
 #if !defined (_WIN32) && !defined (_WIN64)
@@ -201,6 +255,128 @@
 }
 
 /**
+   Helper function to parse a ulimit value string
+
+   @param opts ulimit value string to pares
+   @see child_limits
+*/
+static bool
+parse_limit_opts (const char* opts)
+{
+    static const struct {
+        rw_rlimit* limit;
+        const char* name;
+        const char* caps;
+        const char* mixd;
+        size_t len;
+    } limits[] = {
+        {
+#ifdef RLIMIT_CORE
+            &child_limits.core,
+#else
+            0,
+#endif   // RLIMIT_CORE
+            "core", "CORE", "Core", 4 },
+        {
+#ifdef RLIMIT_CPU
+            &child_limits.cpu,
+#else
+            0,
+#endif   // RLIMIT_CPU
+            "cpu", "CPU", "Cpu", 3 },
+        {
+#ifdef RLIMIT_DATA
+            &child_limits.data,
+#else
+            0,
+#endif   // RLIMIT_DATA
+            "data", "DATA", "Data", 4 },
+        {
+#ifdef RLIMIT_FSIZE
+            &child_limits.fsize,
+#else
+            0,
+#endif   // RLIMIT_FSIZE
+            "fsize", "FSIZE", "Fsize", 5 },
+        {
+#ifdef RLIMIT_NOFILE
+            &child_limits.nofile,
+#else
+            0,
+#endif   // RLIMIT_NOFILE
+            "nofile", "NOFILE", "Nofile", 6 },
+        {
+#ifdef RLIMIT_STACK
+            &child_limits.stack,
+#else
+            0,
+#endif   // RLIMIT_STACK
+            "stack", "STACK", "Stack", 5 },
+        {
+#ifdef RLIMIT_AS
+            &child_limits.as,
+#else
+            0,
+#endif   // RLIMIT_AS    
+            "as", "AS", "As", 2 },
+        { 0, 0, 0, 0, 0 }
+    };
+
+    const char* arg = opts;
+
+    assert (0 != opts);
+
+    while (arg && *arg) {
+
+        const size_t arglen = strlen (arg);
+
+        for (size_t i = 0; limits [i].name; ++i) {
+            if (   limits [i].len < arglen
+                && (   0 == memcmp (limits [i].name, arg, limits [i].len)
+                    || 0 == memcmp (limits [i].caps, arg, limits [i].len)
+                    || 0 == memcmp (limits [i].mixd, arg, limits [i].len))
+                && ':' == arg [limits [i].len]) {
+
+                // determine whether the hard limit and/or
+                // the soft limit should be set
+                const bool hard = isupper (arg [0]);
+                const bool soft = islower (arg [1]);
+
+                arg += limits [i].len + 1;
+
+                char *end;
+                const long lim = strtol (arg, &end, 10);
+
+                arg = end;
+
+                if ('\0' != *arg && ',' != *arg)
+                    break;
+
+                if (limits [i].limit) {
+                    if (soft)
+                        limits [i].limit->rlim_cur = lim;
+
+                    if (hard)
+                        limits [i].limit->rlim_max = lim;
+                } else
+                    warn ("Unable to process %s limit: Not supported\n", 
+                          limits [i].name);
+                break;
+            }
+        }
+
+        if (',' == *arg) {
+            ++arg;
+        }
+        else if ('\0' != *arg) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+/**
     Helper function to produce 'Bad argument' error message.
     
     @param opt name of option encountered
@@ -266,6 +442,7 @@
     const char opt_nocompat[] = "--nocompat";
     const char opt_signal[]   = "--signal";
     const char opt_sleep[]    = "--sleep";
+    const char opt_ulimit[]   = "--ulimit";
 
     int i;
 
@@ -397,7 +574,16 @@
                     }
                 }
             }
-
+            else if (   sizeof opt_ulimit <= arglen
+                     && !memcmp (opt_ulimit, argv [i], sizeof opt_ulimit - 1)) {
+                optname = opt_ulimit;
+                optarg  = get_long_val (argv, &i, sizeof opt_ulimit - 1);
+                if (optarg && *optarg) {
+                    if (!parse_limit_opts (optarg)) {
+                        break;
+                    }
+                }
+            }
             /* fall through */
         }
         default:

Modified: incubator/stdcxx/trunk/util/cmdopt.h
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/cmdopt.h?view=diff&rev=443135&r1=443134&r2=443135
==============================================================================
--- incubator/stdcxx/trunk/util/cmdopt.h (original)
+++ incubator/stdcxx/trunk/util/cmdopt.h Wed Sep 13 14:39:22 2006
@@ -27,6 +27,10 @@
 #ifndef RW_PARSE_OPTS_H
 #define RW_PARSE_OPTS_H
 
+#if !defined (_WIN32) && !defined (_WIN64)
+#  include <unistd.h> /* For _XOPEN_UNIX */
+#endif
+
 extern int timeout;
 extern int compat;
 extern unsigned verbose; /**< Verbose output mode switch.  Defaults to 0 */
@@ -38,6 +42,41 @@
 extern const char default_path_sep; /**< Primary path seperator */
 extern const char suffix_sep; /**< File suffix seperator. */
 extern const size_t exe_suffix_len; /**< Length of executable suffix. */
+
+#ifdef _XOPEN_UNIX
+#  include <sys/resource.h> /* for struct rlimit */
+/**
+   Abstraction typedef for struct rlimit using real struct
+*/
+typedef struct rlimit rw_rlimit;
+#else
+/**
+   Placeholder rlim_t for use in rw_rlimit
+*/
+typedef unsigned long rw_rlim_t;
+/**
+   Placeholder struct rlimit to use if _XOPEN_UNIX isn't defined
+*/
+struct rw_rlimit {
+    rw_rlim_t rlim_cur;
+    rw_rlim_t rlim_max;
+};
+/**
+   Abstraction typedef for struct rlimit using placeholder struct
+*/
+typedef struct rw_rlimit rw_rlimit;
+#endif
+
+extern struct limit_set {
+    rw_rlimit core;
+    rw_rlimit cpu;
+    rw_rlimit data;
+    rw_rlimit fsize;
+    rw_rlimit nofile;
+    rw_rlimit stack;
+    rw_rlimit mem;
+    rw_rlimit as;
+} child_limits; /**< Container holding child process limits. */
 
 void 
 show_usage (int status);

Modified: incubator/stdcxx/trunk/util/exec.cpp
URL: http://svn.apache.org/viewvc/incubator/stdcxx/trunk/util/exec.cpp?view=diff&rev=443135&r1=443134&r2=443135
==============================================================================
--- incubator/stdcxx/trunk/util/exec.cpp (original)
+++ incubator/stdcxx/trunk/util/exec.cpp Wed Sep 13 14:39:22 2006
@@ -40,6 +40,9 @@
 #if !defined (_WIN32) && !defined (_WIN64)
 #  include <unistd.h> /* for close, dup, exec, fork */
 #  include <sys/wait.h>
+#  ifdef _XOPEN_UNIX
+#    include <sys/resource.h> /* for setlimit(), RLIMIT_CORE, ... */
+#  endif
 #else
 #  include <windows.h> /* for PROCESS_INFORMATION, ... */
 #  include <process.h> /* for CreateProcess, ... */
@@ -625,6 +628,70 @@
                    name, strerror (errno));
 }
 
+#ifdef _XOPEN_UNIX
+/**
+    Utility macro to generate an rlimit tuple.
+    
+    @parm val 'short' resource name (no leading RLIMIT_).
+    @param idx limit structure name in child_limits global
+    @see limit_process
+    @see child_limits
+*/
+#undef LIMIT
+#define LIMIT(val, idx)   { RLIMIT_ ## val, &child_limits.idx, #val }
+
+/**
+   Set process resource limits, based on the child_limits global.
+
+   This method uses the LIMIT macro to build an internal array of limits
+   to try setting.  If setrlimit fails
+*/
+static void
+limit_process ()
+{
+    static const struct {
+        int resource;
+        rw_rlimit* limit;
+        const char* name;
+    } limits[] = {
+#ifdef RLIMIT_CORE
+        LIMIT (CORE, core),
+#endif   // RLIMIT_CORE
+#ifdef RLIMIT_CPU
+        LIMIT (CPU, cpu),
+#endif   // RLIMIT_CPU
+#ifdef RLIMIT_DATA
+        LIMIT (DATA, data),
+#endif   // RLIMIT_DATA
+#ifdef RLIMIT_FSIZE
+        LIMIT (FSIZE, fsize),
+#endif   // RLIMIT_FSIZE
+#ifdef RLIMIT_NOFILE
+        LIMIT (NOFILE, nofile),
+#endif   // RLIMIT_NOFILE
+#ifdef RLIMIT_STACK
+        LIMIT (STACK, stack),
+#endif   // RLIMIT_STACK
+#ifdef RLIMIT_AS
+        LIMIT (AS, as),
+#endif   // RLIMIT_AS    
+        { 0, 0, 0 }
+    };
+
+    for (size_t i = 0; limits [i].limit; ++i) {
+        rw_rlimit local;
+
+        memcpy (&local, limits [i].limit, sizeof (struct rlimit));
+
+        if (setrlimit (limits [i].resource, &local)) {
+            warn ("error setting process limits for %s (soft: %lu, hard: "
+                  "%lu): %s\n", limits [i].name, local.rlim_cur, 
+                  local.rlim_max, strerror (errno));
+        }
+    }
+}
+#endif /* _XOPEN_UNIX */
+
 /**
    Entry point to the child process (watchdog) subsystem.
 
@@ -700,6 +767,10 @@
         if (-1 == dup2 (1, 2))
             terminate (1, "Redirection of stderr to stdout failed: %s\n", 
                        strerror (errno));
+
+#ifdef _XOPEN_UNIX
+        limit_process ();
+#endif /* _XOPEN_UNIX */
 
         execv (argv [0], argv);
 



Mime
View raw message