1 /* Copyright (c) 2015 Regents of the University of California
3 * Author: Brian Demsky <bdemsky@uci.edu>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
17 #include <model-assert.h>
21 #include "stacktrace.h"
24 #define MAX_TRACE_LEN 100
26 /** @brief Model-checker output file descriptor; default to stdout until redirected */
27 int model_out = STDOUT_FILENO;
28 int model_err = STDERR_FILENO;
30 #define CONFIG_STACKTRACE
31 /** Print a backtrace of the current program state. */
32 void print_trace(void)
34 #ifdef CONFIG_STACKTRACE
35 print_stacktrace(model_out);
37 void *array[MAX_TRACE_LEN];
41 size = backtrace(array, MAX_TRACE_LEN);
42 strings = backtrace_symbols(array, size);
44 model_print("\nDumping stack trace (%d frames):\n", size);
46 for (i = 0;i < size;i++)
47 model_print("\t%s\n", strings[i]);
50 #endif/* CONFIG_STACKTRACE */
53 void assert_hook(void)
55 model_print("Add breakpoint to line %u in file %s.\n", __LINE__, __FILE__);
58 void model_assert(bool expr, const char *file, int line)
61 printf("Program has hit assertion in file %s at line %d\n",
68 static int fd_user_out; /**< @brief File descriptor from which to read user program output */
71 * @brief Setup output redirecting
73 * Redirects user program's stdout to a pipe so that we can dump it
74 * selectively, when displaying bugs, etc.
75 * Also connects a file descriptor 'model_out' directly to stdout, for printing
78 * The model-checker can selectively choose to print/hide the user program
80 * @see clear_program_output
81 * @see print_program_output
83 * Note that the user program's pipe has limited memory, so if a program will
84 * output much data, we will need to buffer it in user-space during execution.
85 * This also means that if ModelChecker decides not to print an execution, it
86 * should promptly clear the pipe.
88 * This function should only be called once.
90 void redirect_output()
92 /* Save stdout for later use */
93 model_out = dup(STDOUT_FILENO);
99 /* Redirect program output to a pipe */
101 if (pipe(pipefd) < 0) {
105 if (dup2(pipefd[1], STDOUT_FILENO) < 0) {
111 /* Save the "read" side of the pipe for use later */
112 if (fcntl(pipefd[0], F_SETFL, O_NONBLOCK) < 0) {
116 fd_user_out = pipefd[0];
120 * @brief Wrapper for reading data to buffer
122 * Besides a simple read, this handles the subtleties of EOF and nonblocking
123 * input (if fd is O_NONBLOCK).
125 * @param fd The file descriptor to read.
126 * @param buf Buffer to read to.
127 * @param maxlen Maximum data to read to buffer
128 * @return The length of data read. If zero, then we hit EOF or ran out of data
131 static ssize_t read_to_buf(int fd, char *buf, size_t maxlen)
133 ssize_t ret = read(fd, buf, maxlen);
135 if (errno == EAGAIN || errno == EWOULDBLOCK) {
145 /** @brief Dump any pending program output without printing */
146 void clear_program_output()
150 while (read_to_buf(fd_user_out, buf, sizeof(buf))) ;
153 /** @brief Print out any pending program output */
154 void print_program_output()
158 model_print("---- BEGIN PROGRAM OUTPUT ----\n");
160 /* Gather all program output */
163 /* Read program output pipe and write to (real) stdout */
166 ret = read_to_buf(fd_user_out, buf, sizeof(buf));
170 ssize_t res = write(model_out, buf, ret);
179 model_print("---- END PROGRAM OUTPUT ----\n");
181 #endif/* ! CONFIG_DEBUG */