SDL  2.0
SDL_assert.c File Reference
#include "./SDL_internal.h"
#include "SDL.h"
#include "SDL_atomic.h"
#include "SDL_messagebox.h"
#include "SDL_video.h"
#include "SDL_assert.h"
#include "SDL_assert_c.h"
#include "video/SDL_sysvideo.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+ Include dependency graph for SDL_assert.c:

Go to the source code of this file.

Macros

#define ENDLINE   "\n"
 

Functions

static SDL_assert_state SDL_PromptAssertion (const SDL_assert_data *data, void *userdata)
 
static void debug_print (const char *fmt,...)
 
static void SDL_AddAssertionToReport (SDL_assert_data *data)
 
static void SDL_GenerateAssertionReport (void)
 
static void SDL_ExitProcess (int exitcode)
 
static void SDL_AbortAssertion (void)
 
SDL_assert_state SDL_ReportAssertion (SDL_assert_data *data, const char *func, const char *file, int line)
 
void SDL_AssertionsQuit (void)
 
void SDL_SetAssertionHandler (SDL_AssertionHandler handler, void *userdata)
 Set an application-defined assertion handler. More...
 
const SDL_assert_dataSDL_GetAssertionReport (void)
 Get a list of all assertion failures. More...
 
void SDL_ResetAssertionReport (void)
 Reset the list of all assertion failures. More...
 
SDL_AssertionHandler SDL_GetDefaultAssertionHandler (void)
 Get the default assertion handler. More...
 
SDL_AssertionHandler SDL_GetAssertionHandler (void **userdata)
 Get the current assertion handler. More...
 

Variables

static SDL_assert_datatriggered_assertions = NULL
 
static SDL_mutexassertion_mutex = NULL
 
static SDL_AssertionHandler assertion_handler = SDL_PromptAssertion
 
static voidassertion_userdata = NULL
 

Macro Definition Documentation

§ ENDLINE

#define ENDLINE   "\n"

Referenced by SDL_PromptAssertion().

Function Documentation

§ debug_print()

static void debug_print ( const char *  fmt,
  ... 
)
static

Definition at line 66 of file SDL_assert.c.

References SDL_LOG_CATEGORY_ASSERT, SDL_LOG_PRIORITY_WARN, and SDL_LogMessageV.

Referenced by SDL_GenerateAssertionReport(), and SDL_PromptAssertion().

67 {
68  va_list ap;
69  va_start(ap, fmt);
71  va_end(ap);
72 }
#define SDL_LogMessageV

§ SDL_AbortAssertion()

static void SDL_AbortAssertion ( void  )
static

Definition at line 123 of file SDL_assert.c.

References SDL_assert_state, SDL_ExitProcess(), and SDL_Quit.

Referenced by SDL_ReportAssertion().

124 {
125  SDL_Quit();
126  SDL_ExitProcess(42);
127 }
#define SDL_Quit
static void SDL_ExitProcess(int exitcode)
Definition: SDL_assert.c:114

§ SDL_AddAssertionToReport()

static void SDL_AddAssertionToReport ( SDL_assert_data data)
static

Definition at line 75 of file SDL_assert.c.

References triggered_assertions.

Referenced by SDL_ReportAssertion().

76 {
77  /* (data) is always a static struct defined with the assert macros, so
78  we don't have to worry about copying or allocating them. */
79  data->trigger_count++;
80  if (data->trigger_count == 1) { /* not yet added? */
81  data->next = triggered_assertions;
83  }
84 }
static SDL_assert_data * triggered_assertions
Definition: SDL_assert.c:54
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967

§ SDL_AssertionsQuit()

void SDL_AssertionsQuit ( void  )

Definition at line 332 of file SDL_assert.c.

References NULL, SDL_DestroyMutex, and SDL_GenerateAssertionReport().

Referenced by SDL_Quit().

333 {
335  if (assertion_mutex != NULL) {
338  }
339 }
static void SDL_GenerateAssertionReport(void)
Definition: SDL_assert.c:87
#define NULL
Definition: begin_code.h:143
#define SDL_DestroyMutex
static SDL_mutex * assertion_mutex
Definition: SDL_assert.c:56

§ SDL_ExitProcess()

static void SDL_ExitProcess ( int  exitcode)
static

Definition at line 114 of file SDL_assert.c.

Referenced by SDL_AbortAssertion(), and SDL_ReportAssertion().

115 {
116 #ifdef __WIN32__
117  ExitProcess(exitcode);
118 #else
119  _exit(exitcode);
120 #endif
121 }

§ SDL_GenerateAssertionReport()

static void SDL_GenerateAssertionReport ( void  )
static

Definition at line 87 of file SDL_assert.c.

References assertion_handler, debug_print(), NULL, SDL_assert_data, SDL_PromptAssertion(), SDL_ResetAssertionReport(), and triggered_assertions.

Referenced by SDL_AssertionsQuit().

88 {
90 
91  /* only do this if the app hasn't assigned an assertion handler. */
92  if ((item != NULL) && (assertion_handler != SDL_PromptAssertion)) {
93  debug_print("\n\nSDL assertion report.\n");
94  debug_print("All SDL assertions between last init/quit:\n\n");
95 
96  while (item != NULL) {
98  "'%s'\n"
99  " * %s (%s:%d)\n"
100  " * triggered %u time%s.\n"
101  " * always ignore: %s.\n",
102  item->condition, item->function, item->filename,
103  item->linenum, item->trigger_count,
104  (item->trigger_count == 1) ? "" : "s",
105  item->always_ignore ? "yes" : "no");
106  item = item->next;
107  }
108  debug_print("\n");
109 
111  }
112 }
static SDL_AssertionHandler assertion_handler
Definition: SDL_assert.c:57
static SDL_assert_data * triggered_assertions
Definition: SDL_assert.c:54
void SDL_ResetAssertionReport(void)
Reset the list of all assertion failures.
Definition: SDL_assert.c:357
static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
Definition: SDL_assert.c:131
static void debug_print(const char *fmt,...)
Definition: SDL_assert.c:66
#define NULL
Definition: begin_code.h:143
#define SDL_assert_data
Definition: SDL_assert.h:278

§ SDL_GetAssertionHandler()

SDL_AssertionHandler SDL_GetAssertionHandler ( void **  puserdata)

Get the current assertion handler.

This returns the function pointer that is called when an assertion is triggered. This is either the value last passed to SDL_SetAssertionHandler(), or if no application-specified function is set, is equivalent to calling SDL_GetDefaultAssertionHandler().

Parameters
puserdataPointer to a void*, which will store the "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value will always be NULL for the default handler. If you don't care about this data, it is safe to pass a NULL pointer to this function to ignore it.
Returns
The SDL_AssertionHandler that is called when an assert triggers.

Definition at line 376 of file SDL_assert.c.

References assertion_handler, assertion_userdata, and NULL.

377 {
378  if (userdata != NULL) {
379  *userdata = assertion_userdata;
380  }
381  return assertion_handler;
382 }
static SDL_AssertionHandler assertion_handler
Definition: SDL_assert.c:57
static void * assertion_userdata
Definition: SDL_assert.c:58
#define NULL
Definition: begin_code.h:143

§ SDL_GetAssertionReport()

const SDL_assert_data* SDL_GetAssertionReport ( void  )

Get a list of all assertion failures.

Get all assertions triggered since last call to SDL_ResetAssertionReport(), or the start of the program.

The proper way to examine this data looks something like this:

const SDL_AssertData *item = SDL_GetAssertionReport(); while (item) { printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\n", item->condition, item->function, item->filename, item->linenum, item->trigger_count, item->always_ignore ? "yes" : "no"); item = item->next; }

Returns
List of all assertions.
See also
SDL_ResetAssertionReport

Definition at line 352 of file SDL_assert.c.

References triggered_assertions.

353 {
354  return triggered_assertions;
355 }
static SDL_assert_data * triggered_assertions
Definition: SDL_assert.c:54

§ SDL_GetDefaultAssertionHandler()

SDL_AssertionHandler SDL_GetDefaultAssertionHandler ( void  )

Get the default assertion handler.

This returns the function pointer that is called by default when an assertion is triggered. This is an internal function provided by SDL, that is used for assertions when SDL_SetAssertionHandler() hasn't been used to provide a different function.

Returns
The default SDL_AssertionHandler that is called when an assert triggers.

Definition at line 371 of file SDL_assert.c.

References SDL_PromptAssertion().

372 {
373  return SDL_PromptAssertion;
374 }
static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
Definition: SDL_assert.c:131

§ SDL_PromptAssertion()

static SDL_assert_state SDL_PromptAssertion ( const SDL_assert_data data,
void userdata 
)
static

Definition at line 131 of file SDL_assert.c.

References SDL_MessageBoxData::buttons, debug_print(), ENDLINE, SDL_MessageBoxData::flags, SDL_MessageBoxData::message, NULL, SDL_MessageBoxData::numbuttons, SDL_arraysize, SDL_assert_state, SDL_ASSERTION_ABORT, SDL_ASSERTION_ALWAYS_IGNORE, SDL_ASSERTION_BREAK, SDL_ASSERTION_IGNORE, SDL_ASSERTION_RETRY, SDL_getenv, SDL_GetFocusWindow(), SDL_GetWindowFlags, SDL_MAX_LOG_MESSAGE, SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, SDL_MESSAGEBOX_WARNING, SDL_MinimizeWindow, SDL_RestoreWindow, SDL_ShowMessageBox, SDL_snprintf, SDL_stack_alloc, SDL_stack_free, SDL_strcmp, SDL_WINDOW_FULLSCREEN, SDL_zero, state, SDL_MessageBoxData::title, void, window, and SDL_MessageBoxData::window.

Referenced by SDL_GenerateAssertionReport(), SDL_GetDefaultAssertionHandler(), and SDL_SetAssertionHandler().

132 {
133 #ifdef __WIN32__
134  #define ENDLINE "\r\n"
135 #else
136  #define ENDLINE "\n"
137 #endif
138 
139  const char *envr;
142  SDL_MessageBoxData messagebox;
143  SDL_MessageBoxButtonData buttons[] = {
144  { 0, SDL_ASSERTION_RETRY, "Retry" },
145  { 0, SDL_ASSERTION_BREAK, "Break" },
146  { 0, SDL_ASSERTION_ABORT, "Abort" },
148  SDL_ASSERTION_IGNORE, "Ignore" },
150  SDL_ASSERTION_ALWAYS_IGNORE, "Always Ignore" }
151  };
152  char *message;
153  int selected;
154 
155  (void) userdata; /* unused in default handler. */
156 
157  message = SDL_stack_alloc(char, SDL_MAX_LOG_MESSAGE);
158  if (!message) {
159  /* Uh oh, we're in real trouble now... */
160  return SDL_ASSERTION_ABORT;
161  }
163  "Assertion failure at %s (%s:%d), triggered %u %s:" ENDLINE
164  " '%s'",
165  data->function, data->filename, data->linenum,
166  data->trigger_count, (data->trigger_count == 1) ? "time" : "times",
167  data->condition);
168 
169  debug_print("\n\n%s\n\n", message);
170 
171  /* let env. variable override, so unit tests won't block in a GUI. */
172  envr = SDL_getenv("SDL_ASSERT");
173  if (envr != NULL) {
174  SDL_stack_free(message);
175 
176  if (SDL_strcmp(envr, "abort") == 0) {
177  return SDL_ASSERTION_ABORT;
178  } else if (SDL_strcmp(envr, "break") == 0) {
179  return SDL_ASSERTION_BREAK;
180  } else if (SDL_strcmp(envr, "retry") == 0) {
181  return SDL_ASSERTION_RETRY;
182  } else if (SDL_strcmp(envr, "ignore") == 0) {
183  return SDL_ASSERTION_IGNORE;
184  } else if (SDL_strcmp(envr, "always_ignore") == 0) {
186  } else {
187  return SDL_ASSERTION_ABORT; /* oh well. */
188  }
189  }
190 
191  /* Leave fullscreen mode, if possible (scary!) */
192  window = SDL_GetFocusWindow();
193  if (window) {
195  SDL_MinimizeWindow(window);
196  } else {
197  /* !!! FIXME: ungrab the input if we're not fullscreen? */
198  /* No need to mess with the window */
199  window = NULL;
200  }
201  }
202 
203  /* Show a messagebox if we can, otherwise fall back to stdio */
204  SDL_zero(messagebox);
205  messagebox.flags = SDL_MESSAGEBOX_WARNING;
206  messagebox.window = window;
207  messagebox.title = "Assertion Failed";
208  messagebox.message = message;
209  messagebox.numbuttons = SDL_arraysize(buttons);
210  messagebox.buttons = buttons;
211 
212  if (SDL_ShowMessageBox(&messagebox, &selected) == 0) {
213  if (selected == -1) {
214  state = SDL_ASSERTION_IGNORE;
215  } else {
216  state = (SDL_assert_state)selected;
217  }
218  }
219 #ifdef HAVE_STDIO_H
220  else
221  {
222  /* this is a little hacky. */
223  for ( ; ; ) {
224  char buf[32];
225  fprintf(stderr, "Abort/Break/Retry/Ignore/AlwaysIgnore? [abriA] : ");
226  fflush(stderr);
227  if (fgets(buf, sizeof (buf), stdin) == NULL) {
228  break;
229  }
230 
231  if (SDL_strcmp(buf, "a") == 0) {
232  state = SDL_ASSERTION_ABORT;
233  break;
234  } else if (SDL_strcmp(buf, "b") == 0) {
235  state = SDL_ASSERTION_BREAK;
236  break;
237  } else if (SDL_strcmp(buf, "r") == 0) {
238  state = SDL_ASSERTION_RETRY;
239  break;
240  } else if (SDL_strcmp(buf, "i") == 0) {
241  state = SDL_ASSERTION_IGNORE;
242  break;
243  } else if (SDL_strcmp(buf, "A") == 0) {
245  break;
246  }
247  }
248  }
249 #endif /* HAVE_STDIO_H */
250 
251  /* Re-enter fullscreen mode */
252  if (window) {
253  SDL_RestoreWindow(window);
254  }
255 
256  SDL_stack_free(message);
257 
258  return state;
259 }
const char * message
#define SDL_MAX_LOG_MESSAGE
The maximum size of a log message.
Definition: SDL_log.h:54
const char * title
SDL_Window * window
GLuint GLsizei const GLchar * message
static SDL_Window * window
struct xkb_state * state
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
#define SDL_GetWindowFlags
#define SDL_MinimizeWindow
static void debug_print(const char *fmt,...)
Definition: SDL_assert.c:66
Individual button data.
#define SDL_stack_alloc(type, count)
Definition: SDL_stdinc.h:328
SDL_Window * SDL_GetFocusWindow(void)
Definition: SDL_video.c:2534
#define SDL_zero(x)
Definition: SDL_stdinc.h:359
GLenum GLuint GLenum GLsizei const GLchar * buf
const SDL_MessageBoxButtonData * buttons
MessageBox structure containing title, text, window, etc.
#define SDL_RestoreWindow
#define SDL_getenv
#define SDL_ShowMessageBox
#define NULL
Definition: begin_code.h:143
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
#define SDL_assert_state
Definition: SDL_assert.h:277
The type used to identify a window.
Definition: SDL_sysvideo.h:71
#define SDL_snprintf
#define SDL_arraysize(array)
Definition: SDL_stdinc.h:90
#define SDL_strcmp
#define SDL_stack_free(data)
Definition: SDL_stdinc.h:329
#define ENDLINE

§ SDL_ReportAssertion()

SDL_assert_state SDL_ReportAssertion ( SDL_assert_data data,
const char *  func,
const char *  file,
int  line 
)

Definition at line 263 of file SDL_assert.c.

References assertion_handler, assertion_userdata, NULL, SDL_AbortAssertion(), SDL_AddAssertionToReport(), SDL_assert_state, SDL_ASSERTION_ABORT, SDL_ASSERTION_ALWAYS_IGNORE, SDL_ASSERTION_BREAK, SDL_ASSERTION_IGNORE, SDL_ASSERTION_RETRY, SDL_AtomicLock, SDL_AtomicUnlock, SDL_CreateMutex, SDL_ExitProcess(), SDL_LockMutex, SDL_UnlockMutex, and state.

265 {
266  static int assertion_running = 0;
267  static SDL_SpinLock spinlock = 0;
269 
270  SDL_AtomicLock(&spinlock);
271  if (assertion_mutex == NULL) { /* never called SDL_Init()? */
273  if (assertion_mutex == NULL) {
274  SDL_AtomicUnlock(&spinlock);
275  return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
276  }
277  }
278  SDL_AtomicUnlock(&spinlock);
279 
280  if (SDL_LockMutex(assertion_mutex) < 0) {
281  return SDL_ASSERTION_IGNORE; /* oh well, I guess. */
282  }
283 
284  /* doing this because Visual C is upset over assigning in the macro. */
285  if (data->trigger_count == 0) {
286  data->function = func;
287  data->filename = file;
288  data->linenum = line;
289  }
290 
292 
293  assertion_running++;
294  if (assertion_running > 1) { /* assert during assert! Abort. */
295  if (assertion_running == 2) {
297  } else if (assertion_running == 3) { /* Abort asserted! */
298  SDL_ExitProcess(42);
299  } else {
300  while (1) { /* do nothing but spin; what else can you do?! */ }
301  }
302  }
303 
304  if (!data->always_ignore) {
306  }
307 
308  switch (state)
309  {
310  case SDL_ASSERTION_ABORT:
312  return SDL_ASSERTION_IGNORE; /* shouldn't return, but oh well. */
313 
315  state = SDL_ASSERTION_IGNORE;
316  data->always_ignore = 1;
317  break;
318 
320  case SDL_ASSERTION_RETRY:
321  case SDL_ASSERTION_BREAK:
322  break; /* macro handles these. */
323  }
324 
325  assertion_running--;
327 
328  return state;
329 }
static SDL_AssertionHandler assertion_handler
Definition: SDL_assert.c:57
#define SDL_LockMutex
#define SDL_AtomicLock
static void SDL_AbortAssertion(void)
Definition: SDL_assert.c:123
#define SDL_CreateMutex
struct xkb_state * state
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
static void * assertion_userdata
Definition: SDL_assert.c:58
#define SDL_AtomicUnlock
static void SDL_AddAssertionToReport(SDL_assert_data *data)
Definition: SDL_assert.c:75
#define NULL
Definition: begin_code.h:143
#define SDL_assert_state
Definition: SDL_assert.h:277
GLenum func
static SDL_mutex * assertion_mutex
Definition: SDL_assert.c:56
#define SDL_UnlockMutex
int SDL_SpinLock
Definition: SDL_atomic.h:89
static void SDL_ExitProcess(int exitcode)
Definition: SDL_assert.c:114

§ SDL_ResetAssertionReport()

void SDL_ResetAssertionReport ( void  )

Reset the list of all assertion failures.

Reset list of all assertions triggered.

See also
SDL_GetAssertionReport

Definition at line 357 of file SDL_assert.c.

References NULL, SDL_assert_data, SDL_FALSE, and triggered_assertions.

Referenced by SDL_GenerateAssertionReport().

358 {
359  SDL_assert_data *next = NULL;
360  SDL_assert_data *item;
361  for (item = triggered_assertions; item != NULL; item = next) {
362  next = (SDL_assert_data *) item->next;
363  item->always_ignore = SDL_FALSE;
364  item->trigger_count = 0;
365  item->next = NULL;
366  }
367 
369 }
static SDL_assert_data * triggered_assertions
Definition: SDL_assert.c:54
#define NULL
Definition: begin_code.h:143
#define SDL_assert_data
Definition: SDL_assert.h:278

§ SDL_SetAssertionHandler()

void SDL_SetAssertionHandler ( SDL_AssertionHandler  handler,
void userdata 
)

Set an application-defined assertion handler.

This allows an app to show its own assertion UI and/or force the response to an assertion failure. If the app doesn't provide this, SDL will try to do the right thing, popping up a system-specific GUI dialog, and probably minimizing any fullscreen windows.

This callback may fire from any thread, but it runs wrapped in a mutex, so it will only fire from one thread at a time.

Setting the callback to NULL restores SDL's original internal handler.

This callback is NOT reset to SDL's internal handler upon SDL_Quit()!

Returns
SDL_AssertState value of how to handle the assertion failure.
Parameters
handlerCallback function, called when an assertion fails.
userdataA pointer passed to the callback as-is.

Definition at line 341 of file SDL_assert.c.

References assertion_handler, assertion_userdata, NULL, and SDL_PromptAssertion().

342 {
343  if (handler != NULL) {
344  assertion_handler = handler;
345  assertion_userdata = userdata;
346  } else {
349  }
350 }
static SDL_AssertionHandler assertion_handler
Definition: SDL_assert.c:57
static void * assertion_userdata
Definition: SDL_assert.c:58
static SDL_assert_state SDL_PromptAssertion(const SDL_assert_data *data, void *userdata)
Definition: SDL_assert.c:131
#define NULL
Definition: begin_code.h:143

Variable Documentation

§ assertion_handler

§ assertion_mutex

SDL_mutex* assertion_mutex = NULL
static

Definition at line 56 of file SDL_assert.c.

§ assertion_userdata

void* assertion_userdata = NULL
static

§ triggered_assertions