"Fossies" - the Fresh Open Source Software Archive

Member "stress-ng-0.09.56/core-log.c" (15 Mar 2019, 7974 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 "core-log.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 uint16_t abort_fails;    /* count of failures */
   28 static bool abort_msg_emitted;
   29 static FILE *log_file = NULL;
   30 
   31 /*
   32  *  pr_lock()
   33  *  attempt to get a lock, it's just too bad
   34  *  if it fails, this is just to stop messages
   35  *  getting intermixed.
   36  */
   37 void pr_lock(bool *lock)
   38 {
   39 #if defined(HAVE_FLOCK) && defined(LOCK_EX) && defined(LOCK_UN)
   40     int fd, ret;
   41 
   42     *lock = false;
   43 
   44     fd = open("/dev/stdout", O_RDONLY);
   45     if (fd < 0)
   46         return;
   47 
   48     ret = flock(fd, LOCK_EX);
   49     if (ret == 0)
   50         *lock = true;
   51 
   52     (void)close(fd);
   53 #else
   54     (void)lock;
   55 #endif
   56 }
   57 
   58 /*
   59  *  pr_unlock()
   60  *  attempt to unlock
   61  */
   62 void pr_unlock(bool *lock)
   63 {
   64 #if defined(HAVE_FLOCK) && defined(LOCK_EX) && defined(LOCK_UN)
   65     int fd, ret;
   66 
   67     if (!*lock)
   68         return;
   69 
   70     fd = open("/dev/stdout", O_RDONLY);
   71     if (fd < 0)
   72         return;
   73 
   74     ret = flock(fd, LOCK_UN);
   75     if (ret == 0)
   76         *lock = false;
   77 
   78     (void)close(fd);
   79 #else
   80     (void)lock;
   81 #endif
   82 }
   83 
   84 /*
   85  *  pr_fail_check()
   86  *  set rc to EXIT_FAILURE if we detected a pr_fail
   87  *  error condition in the logging during a run.
   88  *  This is horribly indirect but it allows the main
   89  *  stress-ng parent to check that an EXIT_SUCCESS
   90  *  is really a failure based on the logging rather
   91  *  that each stressor doing it's own failure exit
   92  *  return accounting
   93  */
   94 void pr_fail_check(int *const rc)
   95 {
   96     if (abort_msg_emitted && (*rc == EXIT_SUCCESS))
   97         *rc = EXIT_FAILURE;
   98 }
   99 
  100 /*
  101  *  pr_yaml()
  102  *  print to yaml file if it is open
  103  */
  104 int pr_yaml(FILE *fp, const char *const fmt, ...)
  105 {
  106     va_list ap;
  107     int ret = 0;
  108 
  109     va_start(ap, fmt);
  110     if (fp)
  111         ret = vfprintf(fp, fmt, ap);
  112     va_end(ap);
  113 
  114     return ret;
  115 }
  116 
  117 /*
  118  *  pr_closelog()
  119  *  log closing
  120  */
  121 void pr_closelog(void)
  122 {
  123     if (log_file) {
  124         (void)fflush(log_file);
  125         (void)fclose(log_file);
  126         log_file = NULL;
  127     }
  128 }
  129 
  130 /*
  131  *  pr_openlog()
  132  *  optional pr logging to a file
  133  */
  134 void pr_openlog(const char *filename)
  135 {
  136     if (!filename)
  137         return;
  138 
  139     log_file = fopen(filename, "w");
  140     if (!log_file) {
  141         pr_err("Cannot open log file %s\n", filename);
  142         return;
  143     }
  144 }
  145 
  146 static int pr_msg_lockable(
  147     FILE *fp,
  148     const uint64_t flag,
  149     const bool locked,
  150     const char *const fmt,
  151     va_list ap) FORMAT(printf, 4, 0);
  152 
  153 /*
  154  *  pr_msg_lockable()
  155  *  print some debug or info messages with locking
  156  */
  157 static int pr_msg_lockable(
  158     FILE *fp,
  159     const uint64_t flag,
  160     const bool locked,
  161     const char *const fmt,
  162     va_list ap)
  163 {
  164     int ret = 0;
  165     char ts[32];
  166 
  167     if (g_opt_flags & OPT_FLAGS_TIMESTAMP) {
  168         struct timeval tv;
  169 
  170         if (gettimeofday(&tv, NULL) < 0) {
  171             strncpy(ts, "xx-xx-xx.xxx ", sizeof(ts));
  172         } else {
  173             time_t t = tv.tv_sec;
  174             struct tm *tm;
  175 
  176             tm = localtime(&t);
  177             (void)snprintf(ts, sizeof(ts), "%2.2d:%2.2d:%2.2d.%2.2ld ",
  178                 tm->tm_hour, tm->tm_min, tm->tm_sec,
  179                 (long)tv.tv_usec / 10000);
  180         }
  181     } else {
  182         *ts = '\0';
  183     }
  184 
  185     if ((flag & PR_FAIL) || (g_opt_flags & flag)) {
  186         char buf[4096];
  187         const char *type = "";
  188         bool lock = false;
  189 
  190         if (!locked)
  191             pr_lock(&lock);
  192 
  193         if (flag & PR_ERROR)
  194             type = "error:";
  195         if (flag & PR_DEBUG)
  196             type = "debug:";
  197         if (flag & PR_INFO)
  198             type = "info: ";
  199         if (flag & PR_FAIL)
  200             type = "fail: ";
  201 
  202         if (g_opt_flags & OPT_FLAGS_LOG_BRIEF) {
  203             ret = vfprintf(fp, fmt, ap);
  204         } else {
  205             int n = snprintf(buf, sizeof(buf), "%s%s [%d] ",
  206                 ts, type, (int)getpid());
  207             ret = vsnprintf(buf + n, sizeof(buf) - n, fmt, ap);
  208             (void)fprintf(fp, "%s: %s", g_app_name, buf);
  209         }
  210         (void)fflush(fp);
  211 
  212         if (flag & PR_FAIL) {
  213             abort_fails++;
  214             if (abort_fails >= ABORT_FAILURES) {
  215                 if (!abort_msg_emitted) {
  216                     abort_msg_emitted = true;
  217                     g_keep_stressing_flag = false;
  218                     (void)fprintf(fp, "info: %d failures "
  219                         "reached, aborting stress "
  220                         "process\n", ABORT_FAILURES);
  221                     (void)fflush(fp);
  222                 }
  223             }
  224         }
  225 
  226         /* Log messages to log file if --log-file specified */
  227         if (log_file) {
  228             (void)fprintf(log_file, "%s: %s", g_app_name, buf);
  229             (void)fflush(log_file);
  230         }
  231 
  232 #if defined(HAVE_SYSLOG_H)
  233         /* Log messages if syslog requested, don't log DEBUG */
  234         if ((g_opt_flags & OPT_FLAGS_SYSLOG) &&
  235             (!(flag & PR_DEBUG))) {
  236             syslog(LOG_INFO, "%s", buf);
  237         }
  238 
  239         if (!locked)
  240             pr_unlock(&lock);
  241 #endif
  242     }
  243     return ret;
  244 }
  245 
  246 /*
  247  *  __pr_msg_fail()
  248  *  wrapper helper for pr_msg_fail
  249  */
  250 static inline void __pr_msg_fail(const uint64_t flag, const bool locked, char *fmt, ...) FORMAT(printf, 3, 0);
  251 
  252 static inline void __pr_msg_fail(const uint64_t flag, const bool locked, char *fmt, ...)
  253 {
  254     va_list ap;
  255 
  256     va_start(ap, fmt);
  257     (void)pr_msg_lockable(stderr, flag, locked, fmt, ap);
  258     va_end(ap);
  259 }
  260 
  261 PRAGMA_PUSH
  262 PRAGMA_WARN_OFF
  263 /*
  264  *  pr_msg_fail()
  265  *  print failure message with errno
  266  */
  267 void pr_msg_fail(
  268     const uint64_t flag,
  269     const char *name,
  270     const char *what,
  271     const int err)
  272 {
  273     __pr_msg_fail(flag, false, "%s: %s failed, errno=%d (%s)\n",
  274         name, what, err, strerror(err));
  275 }
  276 PRAGMA_POP
  277 
  278 /*
  279  *  pr_dbg()
  280  *  print debug messages
  281  */
  282 void pr_dbg(const char *fmt, ...)
  283 {
  284     va_list ap;
  285 
  286     va_start(ap, fmt);
  287     (void)pr_msg_lockable(stderr, PR_DEBUG, false, fmt, ap);
  288     va_end(ap);
  289 }
  290 
  291 /*
  292  *  pr_dbg_lock()
  293  *  print debug messages with a lock
  294  */
  295 void pr_dbg_lock(bool *lock, const char *fmt, ...)
  296 {
  297     va_list ap;
  298 
  299     /* currently we ignore the locked flag */
  300     (void)lock;
  301 
  302     va_start(ap, fmt);
  303     (void)pr_msg_lockable(stderr, PR_DEBUG, true, fmt, ap);
  304     va_end(ap);
  305 }
  306 
  307 /*
  308  *  pr_inf()
  309  *  print info messages
  310  */
  311 void pr_inf(const char *fmt, ...)
  312 {
  313     va_list ap;
  314 
  315     va_start(ap, fmt);
  316     (void)pr_msg_lockable(stderr, PR_INFO, false, fmt, ap);
  317     va_end(ap);
  318 }
  319 
  320 /*
  321  *  pr_inf()
  322  *  print info messages with a lock
  323  */
  324 void pr_inf_lock(bool *lock, const char *fmt, ...)
  325 {
  326     va_list ap;
  327 
  328     /* currently we ignore the locked flag */
  329     (void)lock;
  330 
  331     va_start(ap, fmt);
  332     (void)pr_msg_lockable(stderr, PR_INFO, true, fmt, ap);
  333     va_end(ap);
  334 }
  335 
  336 /*
  337  *  pr_err()
  338  *  print error messages
  339  */
  340 void pr_err(const char *fmt, ...)
  341 {
  342     va_list ap;
  343 
  344     va_start(ap, fmt);
  345     (void)pr_msg_lockable(stderr, PR_ERROR, false, fmt, ap);
  346     va_end(ap);
  347 }
  348 
  349 /*
  350  *  pr_fail()
  351  *  print failure messages
  352  */
  353 void pr_fail(const char *fmt, ...)
  354 {
  355     va_list ap;
  356 
  357     va_start(ap, fmt);
  358     (void)pr_msg_lockable(stderr, PR_FAIL, false, fmt, ap);
  359     va_end(ap);
  360 }
  361 
  362 /*
  363  *  pr_tidy()
  364  *  print tidy up error messages
  365  */
  366 void pr_tidy(const char *fmt, ...)
  367 {
  368     va_list ap;
  369 
  370     va_start(ap, fmt);
  371     (void)pr_msg_lockable(stderr, g_caught_sigint ? PR_INFO : PR_DEBUG, true, fmt, ap);
  372     va_end(ap);
  373 }
  374 
  375 /*
  376  *  pr_fail_err__()
  377  *  helper for macro pr_fail_err to print error with errno
  378  */
  379 void pr_fail_err__(const args_t *args, const char *msg)
  380 {
  381     pr_msg_fail(PR_FAIL | PR_ERROR, args->name, msg, errno);
  382 }
  383 
  384 /*
  385  *  pr_fail_errno__()
  386  *  helper for macro pr_fail_errno to print error with a given errno
  387  */
  388 void pr_fail_errno__(const args_t *args, const char *msg, int err)
  389 {
  390     pr_msg_fail(PR_FAIL | PR_ERROR, args->name, msg, err);
  391 }
  392 
  393 /*
  394  *  pr_fail_dbg__()
  395  *  helper for macro pr_fail_dbg to print error
  396  */
  397 void pr_fail_dbg__(const args_t *args, const char *msg)
  398 {
  399     pr_msg_fail(PR_DEBUG, args->name, msg, errno);
  400 }