"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-socketpair.c" (15 Mar 2019, 6043 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-socketpair.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 0.09.49_vs_0.09.50.

    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 #define MAX_SOCKET_PAIRS    (32768)
   28 
   29 /*
   30  *  socket_pair_memset()
   31  *  set data to be incrementing chars from val upwards
   32  */
   33 static inline void socket_pair_memset(
   34     uint8_t *buf,
   35     uint8_t val,
   36     const size_t sz)
   37 {
   38     register uint8_t *ptr;
   39     register uint8_t checksum = 0;
   40 
   41     for (ptr = buf + 1 ; ptr < buf + sz; *ptr++ = val++)
   42         checksum += val;
   43     *buf = checksum;
   44 }
   45 
   46 /*
   47  *  socket_pair_memchk()
   48  *  check data contains incrementing chars from val upwards
   49  */
   50 static inline int socket_pair_memchk(
   51     uint8_t *buf,
   52     const size_t sz)
   53 {
   54     register uint8_t *ptr;
   55     register uint8_t checksum = 0;
   56 
   57     for (ptr = buf + 1; ptr < buf + sz; checksum += *ptr++)
   58         ;
   59 
   60     return !(checksum == *buf);
   61 }
   62 
   63 static void socket_pair_close(
   64     int fds[MAX_SOCKET_PAIRS][2],
   65     const int max,
   66     const int which)
   67 {
   68     int i;
   69 
   70     for (i = 0; i < max; i++)
   71         (void)close(fds[i][which]);
   72 }
   73 
   74 /*
   75  *  stress_sockpair_oomable()
   76  *  this stressor needs to be oom-able in the parent
   77  *  and child cases
   78  */
   79 static int stress_sockpair_oomable(const args_t *args)
   80 {
   81     pid_t pid;
   82     int socket_pair_fds[MAX_SOCKET_PAIRS][2], i, max;
   83 
   84     for (max = 0; max < MAX_SOCKET_PAIRS; max++) {
   85         if (socketpair(AF_UNIX, SOCK_STREAM, 0, socket_pair_fds[max]) < 0)
   86             break;
   87     }
   88 
   89     if (max == 0) {
   90         pr_fail_dbg("socket_pair");
   91         return EXIT_FAILURE;
   92     }
   93 
   94 again:
   95     pid = fork();
   96     if (pid < 0) {
   97         if (g_keep_stressing_flag && (errno == EAGAIN))
   98             goto again;
   99         socket_pair_close(socket_pair_fds, max, 0);
  100         socket_pair_close(socket_pair_fds, max, 1);
  101         pr_fail_dbg("fork");
  102         return EXIT_FAILURE;
  103     } else if (pid == 0) {
  104         set_oom_adjustment(args->name, true);
  105         (void)setpgid(0, g_pgrp);
  106         stress_parent_died_alarm();
  107 
  108         socket_pair_close(socket_pair_fds, max, 1);
  109         while (g_keep_stressing_flag) {
  110             uint8_t buf[SOCKET_PAIR_BUF];
  111             ssize_t n;
  112 
  113             for (i = 0; g_keep_stressing_flag && (i < max); i++) {
  114                 n = read(socket_pair_fds[i][0], buf, sizeof(buf));
  115                 if (n <= 0) {
  116                     if ((errno == EAGAIN) || (errno == EINTR))
  117                         continue;
  118                     else if (errno == ENFILE) /* Too many files! */
  119                         goto abort;
  120                     else if (errno == EMFILE) /* Occurs on socket shutdown */
  121                         goto abort;
  122                     else if (errno == EPERM)  /* Occurs on socket closure */
  123                         goto abort;
  124                     else if (errno) {
  125                         pr_fail_dbg("read");
  126                         goto abort;
  127                     }
  128                     continue;
  129                 }
  130                 if ((g_opt_flags & OPT_FLAGS_VERIFY) &&
  131                     socket_pair_memchk(buf, (size_t)n)) {
  132                     pr_fail("%s: socket_pair read error detected, "
  133                         "failed to read expected data\n", args->name);
  134                 }
  135             }
  136         }
  137 abort:
  138         socket_pair_close(socket_pair_fds, max, 0);
  139         _exit(EXIT_SUCCESS);
  140     } else {
  141         uint8_t buf[SOCKET_PAIR_BUF];
  142         int val = 0, status;
  143 
  144         (void)setpgid(pid, g_pgrp);
  145         /* Parent */
  146         socket_pair_close(socket_pair_fds, max, 0);
  147         do {
  148             for (i = 0; keep_stressing() && (i < max); i++) {
  149                 ssize_t ret;
  150 
  151                 socket_pair_memset(buf, val++, sizeof(buf));
  152                 ret = write(socket_pair_fds[i][1], buf, sizeof(buf));
  153                 if (ret <= 0) {
  154                     if ((errno == EAGAIN) || (errno == EINTR))
  155                         continue;
  156                     if (errno) {
  157                         pr_fail_dbg("write");
  158                         break;
  159                     }
  160                     continue;
  161                 }
  162                 inc_counter(args);
  163             }
  164         } while (keep_stressing());
  165 
  166         for (i = 0; i < max; i++) {
  167             if (shutdown(socket_pair_fds[i][1], SHUT_RDWR) < 0)
  168                 pr_fail_dbg("socket shutdown");
  169         }
  170         (void)kill(pid, SIGKILL);
  171         (void)waitpid(pid, &status, 0);
  172         socket_pair_close(socket_pair_fds, max, 1);
  173     }
  174     return EXIT_SUCCESS;
  175 }
  176 
  177 /*
  178  *  stress_sockpair
  179  *  stress by heavy socket_pair I/O
  180  */
  181 static int stress_sockpair(const args_t *args)
  182 {
  183     pid_t pid;
  184     uint32_t restarts = 0;
  185 
  186 again:
  187     pid = fork();
  188     if (pid < 0) {
  189         if (g_keep_stressing_flag && (errno == EAGAIN))
  190             goto again;
  191     } else if (pid > 0) {
  192         int status, ret;
  193 
  194         set_oom_adjustment(args->name, false);
  195 
  196         /* Parent, wait for child */
  197         (void)setpgid(pid, g_pgrp);
  198         ret = waitpid(pid, &status, 0);
  199         if (ret < 0) {
  200             if (errno != EINTR)
  201                 pr_dbg("%s: waitpid(): errno=%d (%s)\n",
  202                     args->name, errno, strerror(errno));
  203             (void)kill(pid, SIGTERM);
  204             (void)kill(pid, SIGKILL);
  205             (void)waitpid(pid, &status, 0);
  206         } else if (WIFSIGNALED(status)) {
  207             pr_dbg("%s: child died: %s (instance %d)\n",
  208                 args->name, stress_strsignal(WTERMSIG(status)),
  209                 args->instance);
  210             /* If we got killed by OOM killer, re-start */
  211             if (WTERMSIG(status) == SIGKILL) {
  212                 log_system_mem_info();
  213                 pr_dbg("%s: assuming killed by OOM killer, "
  214                     "restarting again (instance %d)\n",
  215                     args->name, args->instance);
  216                 restarts++;
  217                 goto again;
  218             }
  219         }
  220      } else if (pid == 0) {
  221         /* Child, lets do some sockpair stressing... */
  222         int ret;
  223 
  224         (void)setpgid(0, g_pgrp);
  225         stress_parent_died_alarm();
  226         set_oom_adjustment(args->name, true);
  227 
  228         ret = stress_sockpair_oomable(args);
  229         _exit(ret);
  230     }
  231 
  232     if (restarts > 0) {
  233         pr_dbg("%s: OOM restarts: %" PRIu32 "\n",
  234             args->name, restarts);
  235     }
  236     return EXIT_SUCCESS;
  237 }
  238 
  239 stressor_info_t stress_sockpair_info = {
  240     .stressor = stress_sockpair,
  241     .class = CLASS_NETWORK | CLASS_OS
  242 };