Skip to content

Commit e4fed74

Browse files
committedJul 27, 2013
debugging improvements
1 parent 51dbbe1 commit e4fed74

File tree

1 file changed

+148
-41
lines changed

1 file changed

+148
-41
lines changed
 

‎src/app/main.cpp

Lines changed: 148 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <cstdio>
4242
#include <stdio.h>
4343
#include <stdlib.h>
44+
#include <stdarg.h>
4445

4546
#ifdef WIN32
4647
// Open files in binary mode
@@ -83,6 +84,8 @@ typedef SInt32 SRefCon;
8384
#include <unistd.h>
8485
#include <execinfo.h>
8586
#include <signal.h>
87+
#include <sys/wait.h>
88+
#include <errno.h>
8689
#endif
8790

8891
/** print usage text
@@ -193,38 +196,159 @@ void qgisCrash( int signal )
193196
{
194197
qFatal( "QGIS died on signal %d", signal );
195198
}
199+
#endif
196200

197-
void dumpBacktrace()
201+
void myPrint( const char *fmt, ... )
198202
{
199-
if ( access( "/usr/bin/c++filt", X_OK ) )
203+
va_list ap;
204+
va_start( ap, fmt );
205+
#if defined(Q_OS_WIN)
206+
char buffer[1024];
207+
vsnprintf( buffer, sizeof buffer, fmt, ap );
208+
OutputDebugString( buffer );
209+
#else
210+
vfprintf( stderr, fmt, ap );
211+
#endif
212+
}
213+
214+
void dumpBacktrace( unsigned int depth = 0 )
215+
{
216+
if ( depth == 0 )
217+
depth = 10;
218+
219+
#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
220+
#if defined(linux) && !defined(ANDROID)
221+
if ( QgsLogger::debugLevel() >= 4 )
222+
{
223+
static int gdbRunning = -1;
224+
static int gdbpipe[2];
225+
static int gdbpid;
226+
227+
if ( gdbRunning == -1 )
228+
{
229+
gdbRunning = 0;
230+
231+
myPrint( "starting gdb\n" );
232+
if ( access( "/usr/bin/gdb", X_OK ) == 0 )
233+
{
234+
// take full stacktrace using gdb
235+
// http://stackoverflow.com/questions/3151779/how-its-better-to-invoke-gdb-from-program-to-print-its-stacktrace
236+
237+
char exename[512];
238+
int len = readlink( "/proc/self/exe", exename, sizeof( exename ) - 1 );
239+
if ( len < 0 )
240+
{
241+
myPrint( "Could not read link.\n" );
242+
}
243+
else
244+
{
245+
exename[ len ] = 0;
246+
247+
if ( pipe( gdbpipe ) == 0 )
248+
{
249+
char pidstr[32];
250+
snprintf( pidstr, sizeof pidstr, "--pid=%d", getpid() );
251+
252+
gdbpid = fork();
253+
fprintf( stderr, "fork returned: %d\n", gdbpid );
254+
if ( gdbpid == 0 )
255+
{
256+
close( STDIN_FILENO ); // close stdin
257+
dup( gdbpipe[0] ); // stdin from pipe
258+
close( gdbpipe[1] ); // close writing end
259+
260+
// attach, backtrace and continue
261+
char btcmd[32];
262+
snprintf( btcmd, sizeof btcmd, "bt full %u", depth );
263+
264+
execl( "/usr/bin/gdb", "gdb", "-q", "-ex", "set height 0", "-n", pidstr, "-ex", "thread", "-ex", btcmd, "-ex", "cont", exename, NULL );
265+
perror( "could not start gdb" );
266+
exit( 0 );
267+
}
268+
else if ( gdbpid >= 0 )
269+
{
270+
close( gdbpipe[0] ); // close reading end
271+
gdbRunning = 1;
272+
}
273+
else
274+
{
275+
myPrint( "Could not start gdb (%d:%s).\n", errno, strerror( errno ) );
276+
}
277+
}
278+
else
279+
{
280+
myPrint( "Could not create pipe (%d:%s).\n", errno, strerror( errno ) );
281+
}
282+
}
283+
}
284+
else
285+
{
286+
myPrint( "gdb not available.\n" );
287+
}
288+
}
289+
else if ( gdbRunning == 1 )
290+
{
291+
myPrint( "Stacktrace (using gdb):\n" );
292+
char btcmd[20];
293+
snprintf( btcmd, sizeof btcmd, "bt full %u\ncont\n", depth );
294+
if ( write( gdbpipe[1], btcmd, strlen( btcmd ) ) == ( int ) strlen( btcmd ) && kill( gdbpid, SIGINT ) == 0 )
295+
return;
296+
297+
myPrint( "write error to gdb [%d:%s]\n", errno, strerror( errno ) );
298+
gdbRunning = 0;
299+
}
300+
}
301+
#endif
302+
303+
if ( access( "/usr/bin/c++filt", X_OK ) < 0 )
200304
{
201-
( void ) write( STDERR_FILENO, "Stacktrace (c++filt NOT FOUND):\n", 32 );
305+
myPrint( "Stacktrace (c++filt NOT FOUND):\n" );
202306
}
203307
else
204308
{
205309
int fd[2];
206310

207311
if ( pipe( fd ) == 0 && fork() == 0 )
208312
{
209-
close( STDIN_FILENO );
210-
close( fd[1] );
211-
dup( fd[0] );
313+
close( STDIN_FILENO ); // close stdin
314+
dup( fd[0] ); // stdin from pipe
315+
close( fd[1] ); // close writing end
212316
execl( "/usr/bin/c++filt", "c++filt", ( char * ) 0 );
317+
perror( "could not start c++filt" );
213318
exit( 1 );
214319
}
215320

216-
( void ) write( STDERR_FILENO, "Stacktrace (piped through c++filt):\n", 36 );
217-
218-
close( STDERR_FILENO );
219-
close( fd[0] );
220-
dup( fd[1] );
321+
myPrint( "Stacktrace (piped through c++filt):\n" );
322+
close( fd[0] ); // close reading end
323+
close( STDERR_FILENO ); // close stderr
324+
dup( fd[1] ); // stderr to pipe
221325
}
222326

223-
void *buffer[256];
224-
int nptrs = backtrace( buffer, sizeof( buffer ) / sizeof( *buffer ) );
327+
void **buffer = new void *[ depth ];
328+
int nptrs = backtrace( buffer, depth );
225329
backtrace_symbols_fd( buffer, nptrs, STDERR_FILENO );
226-
}
330+
delete [] buffer;
331+
#elif defined(Q_OS_WIN)
332+
void **buffer = new void *[ depth ];
333+
334+
SymSetOptions( SYMOPT_DEFERRED_LOADS | SYMOPT_INCLUDE_32BIT_MODULES | SYMOPT_UNDNAME );
335+
SymInitialize( GetCurrentProcess(), "http://msdl.microsoft.com/download/symbols", TRUE );
336+
337+
unsigned short nFrames = CaptureStackBackTrace( 1, depth, buffer, NULL );
338+
SYMBOL_INFO *symbol = ( SYMBOL_INFO * ) qgsMalloc( sizeof( SYMBOL_INFO ) + 256 );
339+
symbol->MaxNameLen = 255;
340+
symbol->SizeOfStruct = sizeof( SYMBOL_INFO );
341+
342+
for ( int i = 0; i < nFrames; i++ )
343+
{
344+
SymFromAddr( GetCurrentProcess(), ( DWORD64 )( buffer[ i ] ), 0, symbol );
345+
symbol->Name[ 255 ] = 0;
346+
myPrint( "%d: %s [%x]\n", i, symbol->Name, symbol->Address );
347+
}
348+
349+
qgsFree( symbol );
227350
#endif
351+
}
228352

229353
/*
230354
* Hook into the qWarning/qFatal mechanism so that we can channel messages
@@ -242,31 +366,19 @@ void myMessageOutput( QtMsgType type, const char *msg )
242366
switch ( type )
243367
{
244368
case QtDebugMsg:
245-
fprintf( stderr, "Debug: %s\n", msg );
246-
#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
369+
myPrint( "%s\n", msg );
247370
if ( strncmp( msg, "Backtrace", 9 ) == 0 )
248-
dumpBacktrace();
249-
#endif
371+
dumpBacktrace( atoi( msg + 9 ) );
250372
break;
251373
case QtCriticalMsg:
252-
fprintf( stderr, "Critical: %s\n", msg );
374+
myPrint( "Critical: %s\n", msg );
253375
break;
254376
case QtWarningMsg:
255-
fprintf( stderr, "Warning: %s\n", msg );
377+
myPrint( "Warning: %s\n", msg );
256378

257379
#ifdef QGISDEBUG
258-
if ( 0 == strncmp( msg, "Object::", 8 )
259-
|| 0 == strncmp( msg, "QWidget::", 9 )
260-
|| 0 == strncmp( msg, "QPainter::", 10 )
261-
)
262-
{
263-
#if 0
264-
#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
265-
dumpBacktrace();
266-
#endif
267-
#endif
268-
QgsMessageLog::logMessage( msg, "Qt" );
269-
}
380+
dumpBacktrace( 20 );
381+
QgsMessageLog::logMessage( msg, "Qt" );
270382
#endif
271383

272384
// TODO: Verify this code in action.
@@ -279,11 +391,9 @@ void myMessageOutput( QtMsgType type, const char *msg )
279391
break;
280392
case QtFatalMsg:
281393
{
282-
fprintf( stderr, "Fatal: %s\n", msg );
283-
#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
284-
dumpBacktrace();
285-
#endif
286-
abort(); // deliberately core dump
394+
myPrint( "Fatal: %s\n", msg );
395+
dumpBacktrace( 256 );
396+
abort(); // deliberately dump core
287397
}
288398
}
289399
}
@@ -299,10 +409,10 @@ int main( int argc, char *argv[] )
299409
#endif // _MSC_VER
300410
#endif // WIN32
301411

302-
#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
303412
// Set up the custom qWarning/qDebug custom handler
304413
qInstallMsgHandler( myMessageOutput );
305414

415+
#if (defined(linux) && !defined(ANDROID)) || defined(__FreeBSD__)
306416
signal( SIGQUIT, qgisCrash );
307417
signal( SIGILL, qgisCrash );
308418
signal( SIGFPE, qgisCrash );
@@ -775,9 +885,6 @@ int main( int argc, char *argv[] )
775885
}
776886
}
777887

778-
#ifdef QGISDEBUG
779-
// QgsDebugMsg(QString("Setting translation to %1/qgis_%2").arg(i18nPath).arg(myTranslationCode));
780-
#endif
781888
QTranslator qgistor( 0 );
782889
if ( qgistor.load( QString( "qgis_" ) + myTranslationCode, i18nPath ) )
783890
{

0 commit comments

Comments
 (0)
Please sign in to comment.