"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-rlimit.c" (15 Mar 2019, 6731 Bytes) of package /linux/privat/stress-ng-0.09.56.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "stress-rlimit.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.52_vs_0.09.54.

    1 /*
    2  * Copyright (C) 2013-2019 Canonical, Ltd.
    3  *
    4  * This program is free software; you can redistribute it and/or
    5  * modify it under the terms of the GNU General Public License
    6  * as published by the Free Software Foundation; either version 2
    7  * of the License, or (at your option) any later version.
    8  *
    9  * This program is distributed in the hope that it will be useful,
   10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12  * GNU General Public License for more details.
   13  *
   14  * You should have received a copy of the GNU General Public License
   15  * along with this program; if not, write to the Free Software
   16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
   17  *
   18  * This code is a complete clean re-write of the stress tool by
   19  * Colin Ian King <colin.king@canonical.com> and attempts to be
   20  * backwardly compatible with the stress tool by Amos Waterland
   21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
   22  * functionality.
   23  *
   24  */
   25 #include "stress-ng.h"
   26 
   27 static volatile bool do_jmp = true;
   28 static sigjmp_buf jmp_env;
   29 
   30 #define MAX_RLIMIT_CPU      (1)
   31 #define MAX_RLIMIT_FSIZE    (1)
   32 #define MAX_RLIMIT_AS       (32 * MB)
   33 #define MAX_RLIMIT_DATA     (16 * MB)
   34 #define MAX_RLIMIT_STACK    (1 * MB)
   35 #define MAX_RLIMIT_NOFILE   (32)
   36 
   37 typedef struct {
   38     const int resource;     /* rlimit resource ID */
   39     const struct rlimit new_limit;  /* new rlimit setting */
   40     struct rlimit old_limit;    /* original old rlimit setting */
   41     int ret;            /* saved old rlimit setting return status */
   42 } limits_t;
   43 
   44 static limits_t limits[] = {
   45 #if defined(RLIMIT_CPU)
   46     { RLIMIT_CPU,   { MAX_RLIMIT_CPU, MAX_RLIMIT_CPU }, { 0, 0 }, false },
   47 #endif
   48 #if defined(RLIMIT_FSIZE)
   49     { RLIMIT_FSIZE, { MAX_RLIMIT_FSIZE, MAX_RLIMIT_FSIZE }, { 0, 0 }, -1 },
   50 #endif
   51 #if defined(RLIMIT_AS)
   52     { RLIMIT_AS,    { MAX_RLIMIT_AS, MAX_RLIMIT_AS }, { 0, 0 }, -1 },
   53 #endif
   54 #if defined(RLIMIT_DATA)
   55     { RLIMIT_DATA,  { MAX_RLIMIT_DATA, MAX_RLIMIT_DATA }, { 0, 0 }, -1 },
   56 #endif
   57 #if defined(RLIMIT_STACK)
   58     { RLIMIT_STACK, { MAX_RLIMIT_STACK, MAX_RLIMIT_STACK }, { 0, 0 }, -1 },
   59 #endif
   60 #if defined(RLIMIT_NOFILE)
   61     { RLIMIT_NOFILE,{ MAX_RLIMIT_NOFILE, MAX_RLIMIT_NOFILE }, { 0, 0 }, -1 },
   62 #endif
   63 };
   64 
   65 /*
   66  *  stress_rlimit_handler()
   67  *  rlimit generic handler
   68  */
   69 static void MLOCKED_TEXT stress_rlimit_handler(int signum)
   70 {
   71     (void)signum;
   72 
   73     if (do_jmp)
   74         siglongjmp(jmp_env, 1);
   75 }
   76 
   77 /*
   78  *  stress_rlimit
   79  *  stress by generating rlimit signals
   80  */
   81 static int stress_rlimit(const args_t *args)
   82 {
   83     struct sigaction old_action_xcpu, old_action_xfsz, old_action_segv;
   84     int fd, pid;
   85     size_t i;
   86     char filename[PATH_MAX];
   87     const double start = time_now();
   88 
   89     if (stress_sighandler(args->name, SIGSEGV, stress_rlimit_handler, &old_action_segv) < 0)
   90         return EXIT_FAILURE;
   91     if (stress_sighandler(args->name, SIGXCPU, stress_rlimit_handler, &old_action_xcpu) < 0)
   92         return EXIT_FAILURE;
   93     if (stress_sighandler(args->name, SIGXFSZ, stress_rlimit_handler, &old_action_xfsz) < 0)
   94         return EXIT_FAILURE;
   95 
   96     (void)stress_temp_filename_args(args,
   97         filename, sizeof(filename), mwc32());
   98     if (stress_temp_dir_mk_args(args) < 0)
   99         return EXIT_FAILURE;
  100     if ((fd = creat(filename, S_IRUSR | S_IWUSR)) < 0) {
  101         pr_fail_err("creat");
  102         (void)stress_temp_dir_rm_args(args);
  103         return EXIT_FAILURE;
  104     }
  105     (void)unlink(filename);
  106 
  107     for (i = 0; i < SIZEOF_ARRAY(limits); i++) {
  108         limits[i].ret = getrlimit(limits[i].resource, &limits[i].old_limit);
  109     }
  110 
  111 again:
  112     pid = fork();
  113     if (pid < 0) {
  114         if (errno == EAGAIN)
  115             goto again;
  116         pr_err("%s: fork failed: errno=%d: (%s)\n",
  117             args->name, errno, strerror(errno));
  118         goto tidy;
  119     } else if (pid > 0) {
  120         int status, waitret;
  121 
  122         /* Parent, wait for child */
  123         (void)setpgid(pid, g_pgrp);
  124         waitret = waitpid(pid, &status, 0);
  125         if (waitret < 0) {
  126             if (errno != EINTR)
  127                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  128                     args->name, errno, strerror(errno));
  129             (void)kill(pid, SIGTERM);
  130             (void)kill(pid, SIGKILL);
  131             (void)waitpid(pid, &status, 0);
  132         } else if (WIFSIGNALED(status)) {
  133             pr_dbg("%s: child died: %s (instance %d)\n",
  134                 args->name, stress_strsignal(WTERMSIG(status)),
  135                 args->instance);
  136             /* If we got killed by OOM killer, re-start */
  137             if (WTERMSIG(status) == SIGKILL) {
  138                 log_system_mem_info();
  139                 pr_dbg("%s: assuming killed by OOM killer, "
  140                     "restarting again (instance %d)\n",
  141                     args->name, args->instance);
  142                 goto again;
  143             }
  144         }
  145     } else if (pid == 0) {
  146         /* Child rlimit stressor */
  147         do {
  148             int ret;
  149 
  150             for (i = 0; i < SIZEOF_ARRAY(limits); i++) {
  151                 (void)setrlimit(limits[i].resource, &limits[i].new_limit);
  152             }
  153 
  154             ret = sigsetjmp(jmp_env, 1);
  155 
  156             /* Check for timer overrun */
  157             if ((time_now() - start) > (double)g_opt_timeout)
  158                 break;
  159             /* Check for counter limit reached */
  160             if (args->max_ops && get_counter(args) >= args->max_ops)
  161                 break;
  162 
  163             if (ret == 0) {
  164                 uint8_t *ptr;
  165                 void *oldbrk;
  166                 int fds[MAX_RLIMIT_NOFILE];
  167 
  168                 switch (mwc32() % 5) {
  169                 default:
  170                 case 0:
  171                     /* Trigger an rlimit signal */
  172                     if (ftruncate(fd, 2) < 0) {
  173                         /* Ignore error */
  174                     }
  175                     break;
  176                 case 1:
  177                     /* Trigger RLIMIT_AS */
  178                     ptr = (uint8_t *)mmap(NULL, MAX_RLIMIT_AS, PROT_READ | PROT_WRITE,
  179                         MAP_ANONYMOUS | MAP_SHARED, -1, 0);
  180                     if (ptr != MAP_FAILED)
  181                         (void)munmap((void *)ptr, MAX_RLIMIT_AS);
  182                     break;
  183                 case 2:
  184                     /* Trigger RLIMIT_DATA */
  185                     oldbrk = shim_sbrk(0);
  186                     if (oldbrk != (void *)-1) {
  187                         ptr = shim_sbrk(MAX_RLIMIT_DATA);
  188                         if (ptr != (void *)-1) {
  189                             int rc = shim_brk(oldbrk);
  190 
  191                             (void)rc;
  192                         }
  193                     }
  194                     break;
  195                 case 3:
  196                     /* Trigger RLIMIT_STACK */
  197                     {
  198                         uint8_t stack[MAX_RLIMIT_STACK];
  199 
  200                         mincore_touch_pages(stack, MAX_RLIMIT_STACK);
  201                     }
  202                     break;
  203                 case 4:
  204                     /* Hit NOFILE limit */
  205                     for (i = 0; i < MAX_RLIMIT_NOFILE; i++) {
  206                         fds[i] = open("/dev/null", O_RDONLY);
  207                     }
  208                     for (i = 0; i < MAX_RLIMIT_NOFILE; i++) {
  209                         if (fds[i] != -1)
  210                             (void)close(fds[i]);
  211                     }
  212                     break;
  213                 }
  214             } else if (ret == 1) {
  215                 inc_counter(args);  /* SIGSEGV/SIGILL occurred */
  216             } else {
  217                 break;      /* Something went wrong! */
  218             }
  219 
  220             for (i = 0; i < SIZEOF_ARRAY(limits); i++) {
  221                 (void)setrlimit(limits[i].resource, &limits[i].old_limit);
  222             }
  223         } while (keep_stressing());
  224 
  225         (void)close(fd);
  226         _exit(0);
  227     }
  228 
  229 tidy:
  230     do_jmp = false;
  231     (void)stress_sigrestore(args->name, SIGXCPU, &old_action_xcpu);
  232     (void)stress_sigrestore(args->name, SIGXFSZ, &old_action_xfsz);
  233     (void)stress_sigrestore(args->name, SIGSEGV, &old_action_segv);
  234     (void)close(fd);
  235     (void)stress_temp_dir_rm_args(args);
  236 
  237     return EXIT_SUCCESS;
  238 }
  239 
  240 stressor_info_t stress_rlimit_info = {
  241     .stressor = stress_rlimit,
  242     .class = CLASS_OS
  243 };