diff --git a/DOCS/man/en/mplayer.1 b/DOCS/man/en/mplayer.1 index be565772fb..ddb61bf80b 100644 --- a/DOCS/man/en/mplayer.1 +++ b/DOCS/man/en/mplayer.1 @@ -472,6 +472,12 @@ Only supported by the cvidix, fbdev, svga, vesa, winvidix, xmga, xvidix and xover video out drivers. . .TP +.B \-crash-debug (DEBUG CODE) +Automatically attaches gdb upon crash or SIGTRAP. +Support must be compiled in by configuring with --enable-crash-debug or +by having a .developer file in the source tree. +. +.TP .B \-edl (EDL only) Enables edit decision list (EDL) actions during playback. Video will be skipped over and audio will be muted and unmuted according to diff --git a/cfg-mplayer.h b/cfg-mplayer.h index a7d5e695e7..53ec4e0d1a 100644 --- a/cfg-mplayer.h +++ b/cfg-mplayer.h @@ -329,6 +329,10 @@ m_option_t mplayer_opts[]={ //---------------------- mplayer-only options ------------------------ +#ifdef CRASH_DEBUG + {"crash-debug", &crash_debug, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL}, + {"nocrash-debug", &crash_debug, CONF_TYPE_FLAG, CONF_GLOBAL, 1, 0, NULL}, +#endif {"osdlevel", &osd_level, CONF_TYPE_INT, CONF_RANGE, 0, 3, NULL}, #ifdef HAVE_MENU {"menu", &use_menu, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL}, diff --git a/configure b/configure index 2c00d023b4..a1f090c89f 100755 --- a/configure +++ b/configure @@ -304,6 +304,7 @@ Advanced options: --enable-debug[=1-3] compile debugging information into mplayer [disable] --enable-profile compile profiling information into mplayer [disable] --disable-sighandler disable sighandler for crashes [enable] + --enable-crash-debug enable automatic gdb attach on crash [disable] --enable-i18n _experimental_ gnu gettext() support [autodetect] --enable-dynamic-plugins Enable support for dynamic a/v plugins [disable] @@ -1355,6 +1356,7 @@ _linux_devfs=no _i18n=auto _dynamic_plugins=no _setlocale=auto +_crash_debug=auto _sighandler=yes _libdv=auto _cdparanoia=auto @@ -1698,6 +1700,12 @@ for ac_option do --disable-debug) _debug= ;; + --enable-crash-debug) + _crash_debug=yes + ;; + --disable-crash-debug) + _crash_debug=no + ;; --enable-sighandler) _sighandler=yes ;; @@ -6173,6 +6181,9 @@ elif test -z "$CFLAGS" ; then # always compile with '-g' if .developer: if test -f ".developer" ; then CFLAGS="-g $CFLAGS" + if (test "$_crash_debug" = auto) && (not mingw32) ; then + _crash_debug=yes + fi _stripbinaries=no fi else @@ -6187,6 +6198,16 @@ To do so, execute 'CFLAGS= ./configure ' EOF fi + +echocheck "automatic gdb attach" +if test "$_crash_debug" = yes ; then + _def_crash_debug='#define CRASH_DEBUG 1' +else + _def_crash_debug='#undef CRASH_DEBUG' + _crash_debug=no +fi +echores "$_crash_debug" + if darwin ; then CFLAGS="$CFLAGS -DSYS_DARWIN" if [ "$_cc_major" = 3 ] && [ "$_cc_minor" -lt 1 ]; then @@ -6581,6 +6602,9 @@ $_def_dynamic_plugins /* enable/disable SIGHANDLER */ $_def_sighandler +/* enable/disable automatic gdb attach on crash, requires SIGHANDLER */ +$_def_crash_debug + /* Toggles debugging informations */ $_def_debug diff --git a/mplayer.c b/mplayer.c index eb6613965e..c3e8ce3318 100644 --- a/mplayer.c +++ b/mplayer.c @@ -504,8 +504,16 @@ static void child_sighandler(int x){ } #endif +#ifdef CRASH_DEBUG +static char *prog_path; +static int crash_debug = 0; +#endif + static void exit_sighandler(int x){ static int sig_count=0; +#ifdef CRASH_DEBUG + if (!crash_debug || x != SIGTRAP) +#endif ++sig_count; if(inited_flags==0 && sig_count>1) exit(1); if(sig_count==5) @@ -527,7 +535,7 @@ static void exit_sighandler(int x){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,"\n" MSGTR_IntBySignal,x, current_module?current_module:mp_gettext("unknown") ); - if(sig_count==1) + if(sig_count<=1) switch(x){ case SIGINT: case SIGQUIT: @@ -545,6 +553,26 @@ static void exit_sighandler(int x){ mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_Exit_SIGSEGV_SIGFPE); default: mp_msg(MSGT_CPLAYER,MSGL_FATAL,MSGTR_Exit_SIGCRASH); +#ifdef CRASH_DEBUG + if (crash_debug) { + int gdb_pid; + char spid[20]; + snprintf(spid, 19, "%i", getpid()); + spid[19] = 0; + mp_msg(MSGT_CPLAYER, MSGL_INFO, "Forking...\n"); + gdb_pid = fork(); + mp_msg(MSGT_CPLAYER, MSGL_INFO, "Forked...\n"); + if (gdb_pid == 0) { // We are the child + if (execlp("gdb", "gdb", prog_path, spid, NULL) == -1) + mp_msg(MSGT_CPLAYER, MSGL_ERR, "Couldn't start gdb\n"); + } else if (gdb_pid < 0) + mp_msg(MSGT_CPLAYER, MSGL_ERR, "Couldn't fork\n"); + else { + waitpid(gdb_pid, NULL, 0); + } + if (x == SIGTRAP) return; + } +#endif } exit_player(NULL); } @@ -1202,6 +1230,9 @@ current_module = NULL; signal(SIGCHLD,child_sighandler); #endif +#ifdef CRASH_DEBUG + prog_path = argv[0]; +#endif //========= Catch terminate signals: ================ // terminate requests: signal(SIGTERM,exit_sighandler); // kill @@ -1217,6 +1248,10 @@ current_module = NULL; signal(SIGILL,exit_sighandler); // illegal instruction signal(SIGFPE,exit_sighandler); // floating point exc. signal(SIGABRT,exit_sighandler); // abort() +#ifdef CRASH_DEBUG + if (crash_debug) + signal(SIGTRAP,exit_sighandler); +#endif #endif #ifdef HAVE_NEW_GUI