Nicolas Bernard's Toolbox - Waypoints

The idea here is to put "waypoints", in the program. When the program crashes on a signal, the signal handler displays the last waypoints before exiting.

Download: dbgpoint.h dbgpoint.c

dbgpoint.h

  1: /*
  2:  * Debugging checkpoints
  3:  *
  4:  * Copyright 2008-2009 Nicolas Bernard <http://www.lafraze.net/nbernard/>
  5:  * All rights reserved.
  6:  *
  7:  * Permission to use, copy, modify, and distribute this software for any
  8:  * purpose with or without fee is hereby granted, provided that the above
  9:  * copyright notice and this permission notice appear in all copies.
 10:  *
 11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 18:  *
 19:  */
 20: 
 21: #ifndef __DBGPOINT_H_
 22: #define __DBGPOINT_H_
 23: 
 24: #define __DBGPOINTMAX 30
 25: 
 26: void dumponsignal(int sig);
 27: 
 28: void dbgpoint(long long int where);
 29: 
 30: int dbgredirectsignal(int sig);
 31: 
 32: #endif /* ! __DBGPOINT_H_ */

dbgpoint.c

  1: /*
  2:  * Debugging checkpoints
  3:  *
  4:  * Copyright 2008-2009 Nicolas Bernard <http://www.lafraze.net/nbernard/>
  5:  * All rights reserved.
  6:  *
  7:  * Permission to use, copy, modify, and distribute this software for any
  8:  * purpose with or without fee is hereby granted, provided that the above
  9:  * copyright notice and this permission notice appear in all copies.
 10:  *
 11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 18:  *
 19:  */
 20: 
 21: #include <sys/time.h>
 22: 
 23: #include <assert.h>
 24: #include <signal.h>
 25: #include <stdlib.h>
 26: #include <string.h>
 27: 
 28: #include "dbgpoint.h"
 29: #include "debug.h"
 30: 
 31: #ifndef NDEBUG
 32: 
 33: unsigned int _dbgpointmax = 30;
 34: 
 35: struct dbgpoint_data {
 36:         long long where;
 37:         struct timeval tv;
 38: };
 39: 
 40: struct dbgpoint_data dbgpoints[__DBGPOINTMAX];
 41: 
 42: static void
 43: dumpdbgpoints(void)
 44: {
 45:         for (int i = 0; i < __DBGPOINTMAX; i++) {
 46:                 struct timeval tv_tmp;
 47:                 timersub(&dbgpoints[i].tv, &dbgpoints[0].tv, &tv_tmp);
 48: 
 49:                 debug("%lld: %lu.%06lu -> %lu.%06lu", dbgpoints[i].where,
 50:                       dbgpoints[i].tv.tv_sec, dbgpoints[i].tv.tv_usec,
 51:                       tv_tmp.tv_sec, tv_tmp.tv_usec);
 52:         }
 53: }
 54: #endif /* ! NDEBUG */
 55: 
 56: void
 57: dumponsignal(int sig)
 58: {
 59:         sigset_t samask, osamask;
 60:         int err = sigfillset(&samask);
 61:         assert(err == 0);
 62:         err = sigprocmask(SIG_BLOCK, &samask, &osamask);
 63:         assert(err == 0);
 64: #ifndef NDEBUG
 65:         dumpdbgpoints();
 66: #endif
 67:         logger(LOG_ERR, "Got signal %d", sig);
 68: 
 69:         dumperrstackstderr();
 70: 
 71:         err = sigprocmask(SIG_SETMASK, &osamask, NULL);
 72:         assert(err == 0);
 73:         abort();
 74: }
 75: 
 76: void
 77: dbgpoint(long long int where)
 78: {
 79: #ifndef NDEBUG
 80:         static unsigned int i = 0;
 81: 
 82:         if (where == 0)
 83:                 i = 0;
 84: 
 85:         if (i >= __DBGPOINTMAX) {
 86:                 i = 1;
 87: /*                debug("i: %u, __DBGPOINTMAX: %u", i, __DBGPOINTMAX);
 88:                 return;*/
 89:         }
 90: 
 91:         dbgpoints[i].where = where;
 92:         gettimeofday(&dbgpoints[i].tv, NULL);
 93:         i++;
 94: #endif
 95:         return;
 96: }
 97: 
 98: int
 99: dbgredirectsignal(int signal)
100: {
101:                 int err;
102:                 struct sigaction sa;
103:                 memset(&sa, 0, sizeof(sa));
104:                 sa.sa_handler = &dumponsignal;
105:                 err = sigaction(signal, &sa, NULL);
106:                 return err;
107: }