core dump on SIGHUP

2005-06-13 Thread Tom Robinson

Configuration Information:
Machine: i686
OS: linux-gnu
Compiler: gcc
Compilation :
uname output: Linux 2.4.20-31.9 i686
Machine Type: i686-pc-linux-gnu

Bash Version: 2.05a
Patch Level: ?
Release Status: release

Description:

I have seen bash dump core a few times.  It is extremely difficult to 
reproduce naturally.
The problem occurs when a SIGHUP is received during a malloc by bash. 
After examining
the backtrace of the core, I am able to reproduce the problem using 
gbd.  I have been able to
reproduce this on a number of different platforms.  After the SIGHUP, 
bash calls a handler
to clean up, write the history, etc.  But it calls free() from 
history_do_write() which in turn
calls internal_free() where the problem occurs.  There is a comment 
right before the xbotch()

but I can't tell if that is relevant here.

Any help on this would be appreciated.

Repeat-By:

# gdb bash
   :
(gdb) break decode_prompt_string
Breakpoint 1 at 0x80600e0: file parse.y, line 3667.
(gdb) r
Starting program: bash

Breakpoint 1, decode_prompt_string (string=0x10b )
   at parse.y:3667
3667  result = (char *)xmalloc (result_size = PROMPT_GROWTH);
(gdb) c
Continuing.
[EMAIL PROTECTED] bin]# ulimit -c 10

Breakpoint 1, decode_prompt_string (string=0x10b )
   at parse.y:3667
3667  result = (char *)xmalloc (result_size = PROMPT_GROWTH);
(gdb) c
Continuing.
[EMAIL PROTECTED] bin]# ulimit -c 100

Breakpoint 1, decode_prompt_string (string=0x10b )
   at parse.y:3667
3667  result = (char *)xmalloc (result_size = PROMPT_GROWTH);
(gdb) c
Continuing.
[EMAIL PROTECTED] bin]# ls
core.23751   bash
   :

Breakpoint 1, decode_prompt_string (string=0x10b )
   at parse.y:3667
3667  result = (char *)xmalloc (result_size = PROMPT_GROWTH);
(gdb) break malloc.c:662
Breakpoint 2 at 0x80ad936: file malloc.c, line 662.
(gdb) c
Continuing.

Breakpoint 2, internal_malloc (n=48,
   file=0x80b01c0 "/usr/src/bash/src/parse.y", line=3667, flags=1)
   at malloc.c:662
662   if ((p = nextf[nunits]) == NULL)


(gdb) signal SIGHUP
Continuing with signal SIGHUP.

Breakpoint 2, internal_malloc (n=20, file=0x0, line=0, flags=0) at malloc.c:662
662   if ((p = nextf[nunits]) == NULL)
(gdb) c
Continuing.

Breakpoint 2, internal_malloc (n=42, file=0x0, line=0, flags=0) at malloc.c:662
662   if ((p = nextf[nunits]) == NULL)
(gdb) c
Continuing.

malloc: unknown:0: assertion botched
free: underflow detected; mh_nbytes out of range
last command: ls
Stopping myself...
Program received signal SIGABRT, Aborted.
0xe002 in ?? ()
(gdb) c
Continuing.

Program received signal SIGABRT, Aborted.
0xe002 in ?? ()
(gdb) bt
#0  0xe002 in ?? ()
#1  0x42028a73 in abort () from /lib/tls/libc.so.6
#2  0x0806c733 in programming_error (
   format=0x80c2b40 "free: underflow detected; mh_nbytes out of range") at
error.c:258
#3  0x080adac4 in internal_free (mem=0x80daa08, file=0x0, line=0, flags=0) at
malloc.c:759
#4  0x080adfd4 in free (mem=0x80daa08) at malloc.c:1073
#5  0x080aae93 in history_do_write (filename=0x80d3968 "/root/.bash_history",
nelements=3,
   overwrite=0) at histfile.c:381
#6  0x080aaeff in append_history (nelements=3, filename=0x80d3968
"/root/.bash_history")
   at histfile.c:398
#7  0x0808068a in maybe_save_shell_history () at bashhist.c:344
#8  0x0807c694 in termination_unwind_protect (sig=1) at sig.c:409
#9  
#10 internal_malloc (n=48, file=0x80b01c0
"/usr/src/bash/src/parse.y",
   line=3667, flags=134627174) at malloc.c:662
#11 0x080adeee in sh_malloc (bytes=48,
   file=0x80b01c0 "/usr/src/bash/src/parse.y", line=3667) at
malloc.c:987
#12 0x080890e9 in sh_xmalloc (bytes=48,
   file=0x80b01c0 "/usr/src/parse.y", line=3667) at
xmalloc.c:143
#13 0x080600fe in decode_prompt_string (string=0x80d9b48 "[EMAIL PROTECTED] \\W]\\$ 
")
   at parse.y:3667
#14 0x0806005a in prompt_again () at parse.y:3583
#15 0x0805d791 in yylex () at parse.y:1964
#16 0x0805c80e in yyparse () at bison.simple:432
#17 0x0805b7cf in parse_command () at eval.c:213
#18 0x0805b83e in read_command () at eval.c:257
#19 0x0805b583 in reader_loop () at eval.c:124
#20 0x08059beb in main (argc=1, argv=0xbfffeb74, env=0xbfffeb7c) at shell.c:668
#21 0x42015574 in __libc_start_main () from /lib/tls/libc.so.6




___
Bug-bash mailing list
Bug-bash@gnu.org
http://lists.gnu.org/mailman/listinfo/bug-bash


Re: core dump on SIGHUP

2005-06-14 Thread Tom Robinson
This problem can be fixed by applying part of the update from 2.05a to 2.05b 
in
lib/malloc/malloc.c.  The relevent sections are as follows:

--- bash-2.05a.orig/lib/malloc/malloc.c 2001-10-04 12:13:16.0 +
+++ bash-2.05a/lib/malloc/malloc.c  2005-06-14 17:19:00.0 +
@@ -202,9 +202,16 @@
 #define ERR_ASSERT_FAILED  0x08

 /* Evaluates to true if NB is appropriate for bucket NU.  NB is adjusted
-   appropriately by the caller to account for malloc overhead. */
-#define IN_BUCKET(nb, nu) \
-  ((nb) > (4 << (nu)) && ((nb) <= (8 << (nu
+   appropriately by the caller to account for malloc overhead.  This only
+   checks that the recorded size is not too big for the bucket.  We
+   can't check whether or not it's in between NU and NU-1 because we
+   might have encountered a busy bucket when allocating and moved up to
+   the next size.*/
+#define IN_BUCKET(nb, nu)  ((nb) <= binsizes[(nu)])
+
+/* Use this when we want to be sure that NB is in bucket NU. */
+#define RIGHT_BUCKET(nb, nu) \
+(((nb) > binsizes[(nu)-1]) && ((nb) <= binsizes[(nu)]))

 /* nextf[i] is free list of blocks of size 2**(i + 3)  */

@@ -218,6 +225,17 @@
 static int pagebucket; /* bucket for requests a page in size */
 static int maxbuck;/* highest bucket receiving allocation request. */

+static unsigned long binsizes[NBUCKETS] = {
+   8UL, 16UL, 32UL, 64UL, 128UL, 256UL, 512UL, 1024UL, 2048UL, 4096UL,
+   8192UL, 16384UL, 32768UL, 65536UL, 131072UL, 262144UL, 524288UL,
+   1048576UL, 2097152UL, 4194304UL, 8388608UL, 16777216UL, 33554432UL,
+   67108864UL, 134217728UL, 268435456UL, 536870912UL, 1073741824UL,
+   2147483648UL, 4294967295UL
+};
+
+/* binsizes[x] == (1 << ((x) + 3)) */
+#define binsize(x)  binsizes[(x)]
+
 /* Declarations for internal functions */
 static PTR_T internal_malloc __P((size_t, const char *, int, int));
 static PTR_T internal_realloc __P((PTR_T, size_t, const char *, int, int));
@@ -753,8 +771,10 @@
  We sanity-check the value of mh_nbytes against the size of the blocks
  in the appropriate bucket before we use it.  This can still cause 
problems
  and obscure errors if mh_nbytes is wrong but still within range; the
- checks against MAGIC1 will probably fail then.  Using MALLOC_REGISTER
- will help here, since it saves the original number of bytes requested. 
*/
+ checks against the size recorded at the end of the chunk will probably
+ fail then.  Using MALLOC_REGISTER will help here, since it saves the
+ original number of bytes requested. */
+
   if (IN_BUCKET(nbytes, nunits) == 0)
 xbotch (mem, ERR_UNDERFLOW,
"free: underflow detected; mh_nbytes out of range", file, line);
@@ -837,8 +857,9 @@
  We sanity-check the value of mh_nbytes against the size of the blocks
  in the appropriate bucket before we use it.  This can still cause 
problems
  and obscure errors if mh_nbytes is wrong but still within range; the
- checks against MAGIC1 will probably fail then.  Using MALLOC_REGISTER
- will help here, since it saves the original number of bytes requested. 
*/
+ checks against the size recorded at the end of the chunk will probably
+ fail then.  Using MALLOC_REGISTER will help here, since it saves the
+ original number of bytes requested. */
   if (IN_BUCKET(nbytes, nunits) == 0)
 xbotch (mem, ERR_UNDERFLOW,
"realloc: underflow detected; mh_nbytes out of range", file, line);
@@ -851,7 +872,7 @@
   nbytes = ALLOCATED_BYTES(n);

   /* If ok, use the same block, just marking its size as changed.  */
-  if (IN_BUCKET(nbytes, nunits))
+  if (RIGHT_BUCKET(nbytes, nunits))
 {
   m = (char *)mem + tocopy;
   *m++ = 0;  *m++ = 0;  *m++ = 0;  *m++ = 0;

---
"Tom Robinson" <[EMAIL PROTECTED]> wrote in message 
news:[EMAIL PROTECTED]
...
> I have seen bash dump core a few times.  It is extremely difficult to 
> reproduce naturally.
> The problem occurs when a SIGHUP is received during a malloc by bash. 
> After examining
> the backtrace of the core, I am able to reproduce the problem using gbd. 
> I have been able to
> reproduce this on a number of different platforms.  After the SIGHUP, bash 
> calls a handler
> to clean up, write the history, etc.  But it calls free() from 
> history_do_write() which in turn
> calls internal_free() where the problem occurs.  There is a comment right 
> before the xbotch()
> but I can't tell if that is relevant here.
>
> Any help on this would be appreciated.
>
> Repeat-By:
>
> # gdb bash
>:
> (gdb) break decode_prompt_string
> Breakpoint 1 at 0x80600e0: file parse.y, line 3667.
> (gdb) r
> Starting program: bash
>
> Breakpoint 1, decode_prompt_string (string=0x10b  bounds>)
>at parse.y:3667
> 3667   result = (char *)xm