Bug#230050: getcontext doesn't report alternate stack correctly
Package: libc6
Version: 2.2.5-11.5
This is a followup to Debian bug 136249. Herbert Xu suggested that I
refile the getcontext part of that bug against libc6.
The problem is that getcontext does not fill in the correct
information when it is executed on the alternate stack. A sample
program illustrating the problem is shown below.
I am using this kernel:
$ uname -a
Linux penguin 2.4.18-bf2.4 #1 Son Apr 14 09:53:28 CEST 2002 i686 unknown unknown GNU/Linux
When I compile and run the following program, it outputs this:
handler context's : stack_base=(nil) stack_size=0 flags=0
it should be : stack_base=0x80499c0 stack_size=2000 flags=1
The program works correctly on Solaris 8, i.e. the "handler's context"
line contains the same numbers as the "it should be" line.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <ucontext.h>
#include <unistd.h>
#include <string.h>
stack_t st;
unsigned
use_up_all_the_stack (char const *p)
{
char array[2048];
array[0] = 1;
return *p + use_up_all_the_stack (array);
}
/* Storage for the alternate signal stack. */
static union
{
char buffer[SIGSTKSZ];
/* These other members are for proper alignment. There's no
standard way to guarantee stack alignment, but this seems enough
in practice. */
long double ld;
long l;
void *p;
} alternate_signal_stack;
void
segv_handler (int signo, siginfo_t *info, void *context)
{
ucontext_t handler_context;
char buf[1024];
if (getcontext (&handler_context) != 0)
abort ();
sprintf (buf,
("handler context's : stack_base=%p stack_size=%lx flags=%d\n"
"it should be : stack_base=%p stack_size=%lx flags=%d\n"),
handler_context.uc_stack.ss_sp,
(unsigned long) handler_context.uc_stack.ss_size,
handler_context.uc_stack.ss_flags,
st.ss_sp, (unsigned long) st.ss_size, SS_ONSTACK);
write (STDERR_FILENO, buf, strlen (buf));
_exit (0);
}
int
main (void)
{
struct sigaction act;
int r;
st.ss_flags = 0;
st.ss_sp = alternate_signal_stack.buffer;
st.ss_size = sizeof alternate_signal_stack.buffer;
r = sigaltstack (&st, 0);
if (r != 0)
abort ();
act.sa_flags = SA_NODEFER | SA_ONSTACK | SA_RESETHAND | SA_SIGINFO;
act.sa_sigaction = segv_handler;
if (sigemptyset (&act.sa_mask) != 0)
abort ();
if (sigaction (SIGSEGV, &act, 0) != 0)
abort ();
return use_up_all_the_stack ("");
}
Reply to: