This is the mail archive of the
gdb@sourceware.cygnus.com
mailing list for the GDB project.
Re: x86 linux GDB and SIGALRM
- To: Mark Kettenis <kettenis at wins dot uva dot nl>
- Subject: Re: x86 linux GDB and SIGALRM
- From: Jonathan Larmour <jlarmour at redhat dot co dot uk>
- Date: Mon, 10 Apr 2000 22:21:18 +0100
- CC: gdb at sourceware dot cygnus dot com
- Organization: Red Hat UK Ltd.
- References: <38DBF46A.8EABE9BF@redhat.co.uk> <38DF3159.DF837D7D@cygnus.com> <200003271020.MAA25618@landau.wins.uva.nl>
Mark Kettenis wrote:
>
> Date: Mon, 27 Mar 2000 20:00:57 +1000
> From: Andrew Cagney <ac131313@cygnus.com>
>
> Jonathan Larmour wrote:
> >
> > I have an x86 Linux program here that uses SIGALRM for regular
> > periodic "interrupts". SIGVTALRM isn't really precise enough for
> > it's needs.
> >
> > However I noticed that "si" doesn't work - it interferes with the
> > ptrace/GDB interface. It seems that when
> > ptrace(PTRACE_SINGLESTEP,...) returns, a SIGALRM is pending, and
> > the single step gets lost.
> >
> > Now this works in GDB 4.18 so this is a regression. But does
> > anyone have any clues as to what's *meant* to be going on here,
> > and how I fix GDB?
>
> Can anyone independantly confirm/deny this?
>
> No, but I'd like to see if I can reproduce the problem. Jonathan, can
> you provide a small test program and detailed instructions (typescript
> of a GDB session) on how to do that?
>
> I know there are problems with single stepping through signal
> handlers. These problems were present in 4.18. They were just masked
> because 4.18 failed to recognize signal handlers. Fixing it is not
> easy, and will require changes to handle_inferior_event(), that I
> prefer not to make before the 5.0 release.
Sorry for the delay in getting back to you on this. I've attached a test
case for you. Virtual timers are no problem, it's only real-time timers
that cause the problem.
Here's a GDB session. As you can see "stepi"s don't work, but "step"s and
"next"s do.
(gdb) b breakme
Breakpoint 1 at 0x80484ee: file sigalrm.c, line 19.
(gdb) run
Starting program: /n/tikka/home/jlarmour/c/sigalrm
Breakpoint 1, breakme () at sigalrm.c:19
19 struct timeval tv = { 0, 0 };
(gdb) disp/i $pc
1: x/i $eip 0x80484ee <breakme+6>: movl $0x0,0xfffffff8(%ebp)
(gdb) si
19 struct timeval tv = { 0, 0 };
1: x/i $eip 0x80484ee <breakme+6>: movl $0x0,0xfffffff8(%ebp)
(gdb)
19 struct timeval tv = { 0, 0 };
1: x/i $eip 0x80484ee <breakme+6>: movl $0x0,0xfffffff8(%ebp)
(gdb)
19 struct timeval tv = { 0, 0 };
1: x/i $eip 0x80484ee <breakme+6>: movl $0x0,0xfffffff8(%ebp)
(gdb) step
21 printf("Got %d alarms\n", alarms);
1: x/i $eip 0x80484fc <breakme+20>: add $0xfffffff8,%esp
(gdb) next
Got 8 alarms
22 select(0, NULL, NULL, NULL, &tv);
1: x/i $eip 0x8048512 <breakme+42>: add $0xfffffff4,%esp
(gdb) si
22 select(0, NULL, NULL, NULL, &tv);
1: x/i $eip 0x8048512 <breakme+42>: add $0xfffffff4,%esp
(gdb)
22 select(0, NULL, NULL, NULL, &tv);
1: x/i $eip 0x8048512 <breakme+42>: add $0xfffffff4,%esp
(gdb)
When I changed the itimer interval to 50000usecs from 5000usecs, then I got
mixed behaviour with some instructions stepping working, and some not. If
using e.g. 1 second, instruction stepping appears to work. This is
presumably all due to whether a SIGALRM is pending when ptrace returns.
Jifl
--
Red Hat, 35 Cambridge Place, Cambridge, UK. CB2 1NS Tel: +44 (1223) 728762
"Plan to be spontaneous tomorrow." || These opinions are all my own fault
#include <signal.h>
#include <stddef.h>
#include <sys/time.h>
#define ALRM
volatile int alarms;
static void
handler( int signum )
{
alarms++;
}
static void
breakme(void)
{
struct timeval tv = { 0, 0 };
printf("Got %d alarms\n", alarms);
select(0, NULL, NULL, NULL, &tv);
}
int main(int argc, char *argv[])
{
struct sigaction act;
sigset_t set;
struct itimerval itv;
act.sa_handler = &handler;
sigemptyset(&set);
act.sa_mask = set;
act.sa_flags = 0;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGVTALRM, &act, NULL);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 5000;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 5000;
#ifdef ALRM
setitimer(ITIMER_REAL, &itv, NULL);
#else
setitimer(ITIMER_VIRTUAL, &itv, NULL);
#endif
for (;;)
breakme();
return 0;
}