"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/stress-sigpipe.c" (15 Mar 2019, 3641 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-sigpipe.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 const args_t *s_args;
   28 
   29 #define CLONE_STACK_SIZE    (16 * 1024)
   30 
   31 static void stress_sigpipe_handler(int signum)
   32 {
   33     (void)signum;
   34 
   35     if (LIKELY(s_args != NULL))
   36         inc_counter(s_args);
   37 }
   38 
   39 static int NORETURN pipe_child(void *ptr)
   40 {
   41     (void)ptr;
   42 
   43     _exit(EXIT_SUCCESS);
   44 }
   45 
   46 static inline int stress_sigpipe_write(
   47     const args_t *args,
   48     const char *buf,
   49     const size_t buf_len)
   50 {
   51     pid_t pid;
   52     int pipefds[2];
   53 
   54     if (UNLIKELY(pipe(pipefds) < 0)) {
   55         pr_fail_dbg("pipe");
   56         return EXIT_FAILURE;
   57     }
   58 
   59 #if defined(F_SETPIPE_SZ)
   60     /*
   61      *  Try to limit pipe max size to 1 page
   62      *  and hence writes more than this will
   63      *  block and fail with SIGPIPE when
   64      *  the child exits and closes the pipe
   65      */
   66     (void)fcntl(pipefds[1], F_SETPIPE_SZ, args->page_size);
   67 #endif
   68 
   69 again:
   70 #if defined(HAVE_CLONE)
   71     {
   72         static bool clone_enosys = false;
   73 
   74         if (UNLIKELY(clone_enosys)) {
   75             pid = fork();
   76         } else  {
   77             char stack[CLONE_STACK_SIZE];
   78             const ssize_t stack_offset =
   79                 stress_get_stack_direction() *
   80                 (CLONE_STACK_SIZE - 64);
   81             char *stack_top = stack + stack_offset;
   82 
   83             pid = clone(pipe_child, align_stack(stack_top),
   84                 CLONE_VM | CLONE_FS | CLONE_SIGHAND | SIGCHLD, NULL);
   85             /*
   86              *  May not have clone, so fall back to fork instead.
   87              */
   88             if (UNLIKELY((pid < 0) && (errno == ENOSYS))) {
   89                 clone_enosys = true;
   90                 goto again;
   91             }
   92         }
   93     }
   94 #else
   95     pid = fork();
   96 #endif
   97     if (UNLIKELY(pid < 0)) {
   98         if (UNLIKELY(g_keep_stressing_flag && (errno == EAGAIN)))
   99             goto again;
  100         (void)close(pipefds[0]);
  101         (void)close(pipefds[1]);
  102         pr_fail_dbg("fork");
  103         return EXIT_FAILURE;
  104     } else if (pid == 0) {
  105         /* Child, only for non-clone path */
  106         (void)pipe_child((void *)pipefds);
  107         _exit(EXIT_SUCCESS);
  108     } else {
  109         int status;
  110 
  111         /* Parent */
  112         (void)setpgid(pid, g_pgrp);
  113         (void)close(pipefds[0]);
  114 
  115         do {
  116             int ret;
  117 
  118             ret = write(pipefds[1], buf, buf_len);
  119             if (LIKELY(ret <= 0))
  120                 break;
  121         } while (keep_stressing());
  122 
  123         (void)close(pipefds[1]);
  124         (void)kill(pid, SIGKILL);
  125         (void)waitpid(pid, &status, 0);
  126     }
  127     return EXIT_SUCCESS;
  128 }
  129 
  130 /*
  131  *  stress_sigpipe
  132  *  stress by generating SIGPIPE signals on pipe I/O
  133  */
  134 static int stress_sigpipe(const args_t *args)
  135 {
  136     s_args = args;
  137     char buf[args->page_size * 2];
  138 
  139     if (stress_sighandler(args->name, SIGPIPE, stress_sigpipe_handler, NULL) < 0)
  140         return EXIT_FAILURE;
  141 
  142     (void)memset(buf, 0, sizeof buf);
  143 
  144     do {
  145         stress_sigpipe_write(args, buf, sizeof buf);
  146     } while (keep_stressing());
  147     return EXIT_SUCCESS;
  148 }
  149 
  150 stressor_info_t stress_sigpipe_info = {
  151     .stressor = stress_sigpipe,
  152     .class = CLASS_INTERRUPT | CLASS_OS
  153 };