Fix for PR 17247: Block SIGCHLD while initializing Guile.

The problem here is that if a thread other than gdb's main thread
gets a SIGCHLD (it's an asynchronous signal so the kernel will
essentially pick a random thread) then gdb will hang if it is
in sigsuspend when the SIGCHLD is delivered.  The other thread
will see the signal and the sigsuspend won't "wake up".

Guile and libgc should be blocking SIGCHLD in their threads,
but we need to work with Guile 2.0 and libgc 7.4.
The problem first shows up in libgc 7.4 because it is the first
release that enables multiple marker threads by default.

gdb/ChangeLog:

	PR 17247
	* guile.c: #include <signal.h>.
	(_initialize_guile): Block SIGCHLD while initializing Guile.

	Replaces the following, which is reverted.

	2014-07-26  Doug Evans  <xdje42@gmail.com>

	PR 17185
	* configure.ac: Add check for header gc/gc.h.
	Add check for function setenv.
	* configure: Regenerate.
	* config.in: Regenerate.
	* guile/guile.c (_initialize_guile): Add workaround for libgc 7.4.0.
This commit is contained in:
Doug Evans 2014-09-08 22:45:34 -07:00
parent 8374059704
commit 92d8d229d9
5 changed files with 53 additions and 68 deletions

View File

@ -1,3 +1,20 @@
2014-09-08 Doug Evans <xdje42@gmail.com>
PR 17247
* guile.c: #include <signal.h>.
(_initialize_guile): Block SIGCHLD while initializing Guile.
Replaces the following, which is reverted.
2014-07-26 Doug Evans <xdje42@gmail.com>
PR 17185
* configure.ac: Add check for header gc/gc.h.
Add check for function setenv.
* configure: Regenerate.
* config.in: Regenerate.
* guile/guile.c (_initialize_guile): Add workaround for libgc 7.4.0.
2014-09-08 Doug Evans <xdje42@gmail.com>
* guile/scm-cmd.c (gdbscm_parse_command_name): Replace magic number

View File

@ -141,9 +141,6 @@
/* Define if <sys/procfs.h> has fpregset_t. */
#undef HAVE_FPREGSET_T
/* Define to 1 if you have the <gc/gc.h> header file. */
#undef HAVE_GC_GC_H
/* Define to 1 if you have the `getgid' function. */
#undef HAVE_GETGID
@ -348,9 +345,6 @@
/* Define to 1 if you have the `scm_new_smob' function. */
#undef HAVE_SCM_NEW_SMOB
/* Define to 1 if you have the `setenv' function. */
#undef HAVE_SETENV
/* Define to 1 if you have the `setlocale' function. */
#undef HAVE_SETLOCALE

26
gdb/configure vendored
View File

@ -9276,32 +9276,6 @@ else
fi
# PR 17185, see if we can get the libgc version to see if we need
# to apply the workaround.
for ac_header in gc/gc.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "gc/gc.h" "ac_cv_header_gc_gc_h" "$ac_includes_default"
if test "x$ac_cv_header_gc_gc_h" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_GC_GC_H 1
_ACEOF
fi
done
for ac_func in setenv
do :
ac_fn_c_check_func "$LINENO" "setenv" "ac_cv_func_setenv"
if test "x$ac_cv_func_setenv" = x""yes; then :
cat >>confdefs.h <<_ACEOF
#define HAVE_SETENV 1
_ACEOF
fi
done
# --------------------- #
# Check for libmcheck. #
# --------------------- #

View File

@ -1233,11 +1233,6 @@ AC_SUBST(GUILE_CPPFLAGS)
AC_SUBST(GUILE_LIBS)
AM_CONDITIONAL(HAVE_GUILE, test "${have_libguile}" != no)
# PR 17185, see if we can get the libgc version to see if we need
# to apply the workaround.
AC_CHECK_HEADERS(gc/gc.h)
AC_CHECK_FUNCS([setenv])
# --------------------- #
# Check for libmcheck. #
# --------------------- #

View File

@ -34,10 +34,8 @@
#ifdef HAVE_GUILE
#include "guile.h"
#include "guile-internal.h"
#ifdef HAVE_GC_GC_H
#include <gc/gc.h> /* PR 17185 */
#endif
#endif
#include <signal.h>
/* The Guile version we're using.
We *could* use the macros in libguile/version.h but that would preclude
@ -833,39 +831,46 @@ extern initialize_file_ftype _initialize_guile;
void
_initialize_guile (void)
{
char *msg;
install_gdb_commands ();
#if HAVE_GUILE
/* The Python support puts the C side in module "_gdb", leaving the Python
side to define module "gdb" which imports "_gdb". There is evidently no
similar convention in Guile so we skip this. */
/* PR 17185 There are problems with using libgc 7.4.0.
Copy over the workaround Guile uses (Guile is working around a different
problem, but the workaround is the same). */
#if (GC_VERSION_MAJOR == 7 && GC_VERSION_MINOR == 4 && GC_VERSION_MICRO == 0)
/* The bug is only known to appear with pthreads. We assume any system
using pthreads also uses setenv (and not putenv). That is why we don't
have a similar call to putenv here. */
#if defined (HAVE_SETENV)
setenv ("GC_MARKERS", "1", 1);
#endif
{
#ifdef HAVE_SIGPROCMASK
sigset_t sigchld_mask, prev_mask;
#endif
/* scm_with_guile is the most portable way to initialize Guile.
Plus we need to initialize the Guile support while in Guile mode
(e.g., called from within a call to scm_with_guile). */
scm_with_guile (call_initialize_gdb_module, NULL);
/* The Python support puts the C side in module "_gdb", leaving the Python
side to define module "gdb" which imports "_gdb". There is evidently no
similar convention in Guile so we skip this. */
/* Set Guile's backtrace to match the "set guile print-stack" default.
[N.B. The two settings are still separate.]
But only do this after we've initialized Guile, it's nice to see a
backtrace if there's an error during initialization.
OTOH, if the error is that gdb/init.scm wasn't found because gdb is being
run from the build tree, the backtrace is more noise than signal.
Sigh. */
gdbscm_set_backtrace (0);
#ifdef HAVE_SIGPROCMASK
/* Before we initialize Guile, block SIGCHLD.
This is done so that all threads created during Guile initialization
have SIGCHLD blocked. PR 17247.
Really libgc and Guile should do this, but we need to work with
libgc 7.4.x. */
sigemptyset (&sigchld_mask);
sigaddset (&sigchld_mask, SIGCHLD);
sigprocmask (SIG_BLOCK, &sigchld_mask, &prev_mask);
#endif
/* scm_with_guile is the most portable way to initialize Guile.
Plus we need to initialize the Guile support while in Guile mode
(e.g., called from within a call to scm_with_guile). */
scm_with_guile (call_initialize_gdb_module, NULL);
#ifdef HAVE_SIGPROCMASK
sigprocmask (SIG_SETMASK, &prev_mask, NULL);
#endif
/* Set Guile's backtrace to match the "set guile print-stack" default.
[N.B. The two settings are still separate.]
But only do this after we've initialized Guile, it's nice to see a
backtrace if there's an error during initialization.
OTOH, if the error is that gdb/init.scm wasn't found because gdb is
being run from the build tree, the backtrace is more noise than signal.
Sigh. */
gdbscm_set_backtrace (0);
}
#endif
}