Configuration Information [Automatically generated, do not change]:
Machine: i586
OS: linux-gnu
Compiler: gcc -I/usr/src/packages/BUILD/bash-4.1
-L/usr/src/packages/BUILD/bash-4.1/../readline-6.1
Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='i586'
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='i586-suse-linux-gnu'
-DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL
-DHAVE_CONFIG_H -I. -I. -I./include -I./lib -O2 -march=i586 -mtune=i686
-fmessage-length=0 -Wall -D_FORTIFY_SOURCE=2 -fstack-protector -funwind-tables
-fasynchronous-unwind-tables -g -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
-D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g -std=gnu89 -Wextra
-Wno-unprototyped-calls -Wno-switch-enum -Wno-unused-variable
-Wno-unused-parameter -ftree-loop-linear -pipe -fprofile-use
uname output: Linux boole 2.6.27.19-3.2-pae #1 SMP 2009-02-25 15:40:44 +0100
i686 i686 i386 GNU/Linux
Machine Type: i586-suse-linux-gnu
Bash Version: 4.1, 4.0, 3.2, 3.1, 3.0
Patch Level: all
Release Status: release
Description:
Signal handler may hang in futex_wait() on fast multi processor systems.
This seems to caused by using stdio within signal handlers in some cases
where glibc uses malloc()/free() internal.
Repeat-By:
This is very hard to reproduce as it requires a fast multi processor
system
combined with a glibc version which triggers this race condition.
See https://bugzilla.novell.com/show_bug.cgi?id=522351
Fix:
For the malloc()/free() used by the bash (confgured with
--without-gnu-malloc
and --without-bash-malloc) I use the patch below but this does not work
for
the in glibc internal used malloc()/free() calls. A real solution
could be
the way done in tcsh or ksh where only flags will be set from the signal
handlers whereas the real work is done within the main loop its self.
--- parse.y
+++ parse.y 2010-01-20 13:51:39.0 +
@@ -1434,10 +1434,11 @@ yy_readline_get ()
current_readline_prompt : "");
terminate_immediately = 0;
- if (signal_is_ignored (SIGINT) == 0 && old_sigint)
+ if (signal_is_ignored (SIGINT) == 0)
{
interrupt_immediately--;
- set_signal_handler (SIGINT, old_sigint);
+ if (old_sigint)
+ set_signal_handler (SIGINT, old_sigint);
}
#if 0
--- xmalloc.c
+++ xmalloc.c 2010-02-24 08:32:51.452626384 +
@@ -35,6 +35,11 @@
# include "ansi_stdlib.h"
#endif /* HAVE_STDLIB_H */
+/* Determine which kind of system this is. */
+#include
+extern int interrupt_immediately;
+extern int signal_is_trapped __P((int));
+
#include "error.h"
#include "bashintl.h"
@@ -94,6 +99,34 @@ allocerr (func, bytes)
#endif /* !HAVE_SBRK */
}
+static void
+block_signals (setp, osetp)
+ sigset_t *setp, *osetp;
+{
+#ifdef HAVE_POSIX_SIGNALS
+ sigfillset (setp);
+ sigemptyset (osetp);
+ sigprocmask (SIG_BLOCK, setp, osetp);
+#else
+# if defined (HAVE_BSD_SIGNALS)
+ *osetp = sigsetmask (-1);
+# endif
+#endif
+}
+
+static void
+unblock_signals (setp, osetp)
+ sigset_t *setp, *osetp;
+{
+#ifdef HAVE_POSIX_SIGNALS
+ sigprocmask (SIG_SETMASK, osetp, (sigset_t *)NULL);
+#else
+# if defined (HAVE_BSD_SIGNALS)
+ sigsetmask (*osetp);
+# endif
+#endif
+}
+
/* Return a pointer to free()able block of memory large enough
to hold BYTES number of bytes. If the memory cannot be allocated,
print an error message and abort. */
@@ -102,15 +135,28 @@ xmalloc (bytes)
size_t bytes;
{
PTR_T temp;
+ sigset_t set, oset;
+ int blocked_sigs;
#if defined (DEBUG)
if (bytes == 0)
internal_warning("xmalloc: size argument is 0");
#endif
+ /* Block all signals in case we are executed from a signal handler. */
+ blocked_sigs = 0;
+ if (interrupt_immediately || signal_is_trapped (SIGINT) || signal_is_trapped
(SIGCHLD))
+{
+ block_signals (&set, &oset);
+ blocked_sigs = 1;
+}
+
FINDBRK();
temp = malloc (bytes);
+ if (blocked_sigs)
+unblock_signals (&set, &oset);
+
if (temp == 0)
allocerr ("xmalloc", bytes);
@@ -123,15 +169,28 @@ xrealloc (pointer, bytes)
size_t bytes;
{
PTR_T temp;
+ sigset_t set, oset;
+ int blocked_sigs;
#if defined (DEBUG)
if (bytes == 0)
internal_warning("xrealloc: size argument is 0");
#endif
+ /* Block all signals in case we are executed from a signal handler. */
+ blocked_sigs = 0;
+ if (interrupt_immediately || signal_is_trapped (SIGINT) || signal_is_trapped
(SIGCHLD))
+{
+ block_signals (&set, &oset);
+ blocked_sigs = 1;
+}
+
FINDBRK();
temp = pointer ? realloc (pointer, bytes) : malloc (bytes);
+ if (blocked_sigs)
+unblock_signals (&set, &oset);
+
if (temp == 0)
allocerr ("xrealloc", bytes);
@@ -145,7 +204,22 @@ xfree (string)
PTR_T string;
{
if (string)
-free (string);
+{
+ sigset_t set,