Samuel Thibault, on Mon 14 Nov 2016 01:07:40 +0100, wrote:
> > Once that's been resolved, then we're back to the problem with signal
> > preemptors!  libpager/pager-memcpy.c includes the following code:
> > 
> >   void fault (int signo, long int sigcode, struct sigcontext *scp)
> >     {
> >       assert (scp->sc_error == EKERN_MEMORY_ERROR);
> >       err = pager_get_error (pager, sigcode - window + offset);
> >       n -= sigcode - window;
> >       vm_deallocate (mach_task_self (), window, window_size);
> >       longjmp (buf, 1);
> >     }
> > 
> > Since sigcode no longer contains the faulting address (it's in the subcode,
> > remember?)
> 
> Mmm, no.  For legacy signal handlers (i.e. without SA_SIGINFO), the
> parameters should still be the sigcode: it's
> _hurd_exception2signal_legacy which should be getting called from
> sysdeps/mach/hurd/i386/trampoline.c.

The attached testcase does get the faulting address.

I really believe the issue is related to this:

> Note that there is a 
> 
>   /* XXX what if handler != action->handler (for instance, if a signal
>    * preemptor took over) ? */
> 
> above.  I'd say that when handler != action->handler we should assume
> it's a legacy handler, and make 'action' point to a default-legacy
> sigaction structure, so that it doesn't have SA_SIGINFO, and thus the
> legacy parameters will be passeD.

Samuel
#define _GNU_SOURCE
#include <sys/types.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <hurd.h>
#include <hurd/sigpreempt.h>

char *c = (char*) 0xa0000000;

error_t
do_copy (struct hurd_signal_preemptor *preemptor)
{
        fprintf(stderr,"copying\n");
        memcpy(c, c+1, 999999);
        fprintf(stderr,"copied\n");
}

int main(int argc, char *argv[]) {
        jmp_buf buf;
        void fault(int signo, long int sigcode, struct sigcontext *scp)
        {
                fprintf(stderr,"%d %lx %p\n", signo, sigcode, scp);
                longjmp(buf, 1);
        }
        if (setjmp(buf) == 0) {
                hurd_catch_signal(sigmask(SIGSEGV) | sigmask(SIGBUS),
                                (unsigned long) c, (unsigned long) c+1000000,
                        &do_copy, (sighandler_t) &fault);
        }
        fprintf(stderr,"done\n");
        return 0;
}

Reply via email to