8 #include <model-assert.h>
12 #include "stacktrace.h"
15 #define MAX_TRACE_LEN 100
17 /** @brief Model-checker output stream; default to stdout until redirected */
18 FILE *model_out = stdout;
20 #define CONFIG_STACKTRACE
21 /** Print a backtrace of the current program state. */
22 void print_trace(void)
24 #ifdef CONFIG_STACKTRACE
25 print_stacktrace(model_out);
27 void *array[MAX_TRACE_LEN];
31 size = backtrace(array, MAX_TRACE_LEN);
32 strings = backtrace_symbols(array, size);
34 model_print("\nDumping stack trace (%d frames):\n", size);
36 for (i = 0; i < size; i++)
37 model_print("\t%s\n", strings[i]);
40 #endif /* CONFIG_STACKTRACE */
43 void model_print_summary(void)
45 model->print_summary();
48 void assert_hook(void)
50 model_print("Add breakpoint to line %u in file %s.\n", __LINE__, __FILE__);
53 void model_assert(bool expr, const char *file, int line)
57 sprintf(msg, "Program has hit assertion in file %s at line %d\n",
59 model->assert_user_bug(msg);
65 static int fd_user_out; /**< @brief File descriptor from which to read user program output */
68 * @brief Setup output redirecting
70 * Redirects user program's stdout to a pipe so that we can dump it
71 * selectively, when displaying bugs, etc.
72 * Also connects a special file 'model_out' directly to stdout, for printing
75 * The model-checker can selectively choose to print/hide the user program
77 * @see clear_program_output
78 * @see print_program_output
80 * Note that the user program's pipe has limited memory, so if a program will
81 * output much data, we will need to buffer it in user-space during execution.
82 * This also means that if ModelChecker decides not to print an execution, it
83 * should promptly clear the pipe.
85 * This function should only be called once.
87 void redirect_output()
91 /* Save stdout for later use */
92 fd = dup(fileno(stdout));
93 model_out = fdopen(fd, "w");
95 /* Redirect program output to a pipe */
97 if (pipe(pipefd) < 0) {
101 fd = dup2(pipefd[1], fileno(stdout)); // STDOUT_FILENO
104 /* Save the "read" side of the pipe for use later */
105 fcntl(pipefd[0], F_SETFL, O_NONBLOCK);
106 fd_user_out = pipefd[0];
110 * @brief Wrapper for reading data to buffer
112 * Besides a simple read, this handles the subtleties of EOF and nonblocking
113 * input (if fd is O_NONBLOCK).
115 * @param fd The file descriptor to read.
116 * @param buf Buffer to read to.
117 * @param maxlen Maximum data to read to buffer
118 * @return The length of data read. If zero, then we hit EOF or ran out of data
121 static ssize_t read_to_buf(int fd, char *buf, size_t maxlen)
123 ssize_t ret = read(fd, buf, maxlen);
125 if (errno == EAGAIN || errno == EWOULDBLOCK) {
135 /** @brief Dump any pending program output without printing */
136 void clear_program_output()
140 while (read_to_buf(fd_user_out, buf, sizeof(buf)));
143 /** @brief Print out any pending program output */
144 void print_program_output()
148 /* Gather all program output */
151 /* Read program output pipe and write to (real) stdout */
154 ret = read_to_buf(fd_user_out, buf, sizeof(buf));
158 int res = fwrite(buf, 1, ret, model_out);
160 errno = ferror(model_out);
168 #endif /* ! CONFIG_DEBUG */