[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: core dump on SIGHUP
From: |
Tom Robinson |
Subject: |
Re: core dump on SIGHUP |
Date: |
Tue, 14 Jun 2005 15:58:04 -0700 |
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.000000000 +0000
+++ bash-2.05a/lib/malloc/malloc.c 2005-06-14 17:19:00.000000000 +0000
@@ -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" <trobinson@mvista.com> wrote in message
news:mailman.54.1118728847.2837.bug-bash@gnu.org...
...
> 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 <Address 0x10b out of
> bounds>)
> at parse.y:3667
> 3667 result = (char *)xmalloc (result_size = PROMPT_GROWTH);
> (gdb) c
> Continuing.
> [root@walstib bin]# ulimit -c 100000
>
> Breakpoint 1, decode_prompt_string (string=0x10b <Address 0x10b out of
> bounds>)
> at parse.y:3667
> 3667 result = (char *)xmalloc (result_size = PROMPT_GROWTH);
> (gdb) c
> Continuing.
> [root@walstib bin]# ulimit -c 10000000000
>
> Breakpoint 1, decode_prompt_string (string=0x10b <Address 0x10b out of
> bounds>)
> at parse.y:3667
> 3667 result = (char *)xmalloc (result_size = PROMPT_GROWTH);
> (gdb) c
> Continuing.
> [root@walstib bin]# ls
> core.23751 bash
> :
>
> Breakpoint 1, decode_prompt_string (string=0x10b <Address 0x10b out of
> bounds>)
> 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.
> 0xffffe002 in ?? ()
> (gdb) c
> Continuing.
>
> Program received signal SIGABRT, Aborted.
> 0xffffe002 in ?? ()
> (gdb) bt
> #0 0xffffe002 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 <signal handler called>
> #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 "[\\u@\\h \\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
>
>
>
>