diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index b858a9ccd..8e0f66f0b 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2015-04-01 Jon TURNEY + + * include/sys/ucontext.h : New header. + * include/ucontext.h : Ditto. + * exceptions.cc (call_signal_handler): Provide ucontext_t + parameter to signal handler function. + 2015-04-01 Jon TURNEY * external.cc (cygwin_internal): Add operation to retrieve a copy diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index af534574b..0d1f36d50 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -16,6 +16,7 @@ details. */ #include #include #include +#include #include "cygtls.h" #include "pinfo.h" @@ -1489,15 +1490,33 @@ _cygtls::call_signal_handler () siginfo_t thissi = infodata; void (*thisfunc) (int, siginfo_t *, void *) = func; + ucontext_t thiscontext; + thiscontext.uc_link = 0; + thiscontext.uc_flags = 0; + if (thissi.si_cyg) + memcpy (&thiscontext.uc_mcontext, ((cygwin_exception *)thissi.si_cyg)->context(), sizeof(CONTEXT)); + else + RtlCaptureContext ((CONTEXT *)&thiscontext.uc_mcontext); + /* FIXME: Really this should be the context which the signal interrupted? */ + + /* FIXME: If/when sigaltstack is implemented, this will need to do + something more complicated */ + thiscontext.uc_stack.ss_sp = NtCurrentTeb ()->Tib.StackBase; + thiscontext.uc_stack.ss_flags = 0; + if (!NtCurrentTeb ()->DeallocationStack) + thiscontext.uc_stack.ss_size = (uintptr_t)NtCurrentTeb ()->Tib.StackLimit - (uintptr_t)NtCurrentTeb ()->Tib.StackBase; + else + thiscontext.uc_stack.ss_size = (uintptr_t)NtCurrentTeb ()->DeallocationStack - (uintptr_t)NtCurrentTeb ()->Tib.StackBase; + sigset_t this_oldmask = set_process_mask_delta (); + thiscontext.uc_sigmask = this_oldmask; int this_errno = saved_errno; reset_signal_arrived (); incyg = false; sig = 0; /* Flag that we can accept another signal */ unlock (); /* unlock signal stack */ - /* no ucontext_t information provided yet, so third arg is NULL */ - thisfunc (thissig, &thissi, NULL); + thisfunc (thissig, &thissi, &thiscontext); incyg = true; set_signal_mask (_my_tls.sigmask, this_oldmask); diff --git a/winsup/cygwin/include/sys/ucontext.h b/winsup/cygwin/include/sys/ucontext.h new file mode 100644 index 000000000..9362d90cd --- /dev/null +++ b/winsup/cygwin/include/sys/ucontext.h @@ -0,0 +1,26 @@ +/* ucontext.h + + Copyright 2015 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _SYS_UCONTEXT_H_ +#define _SYS_UCONTEXT_H_ + +#include + +typedef struct __mcontext mcontext_t; + +typedef struct __ucontext { + struct __ucontext *uc_link; + sigset_t uc_sigmask; + stack_t uc_stack; + mcontext_t uc_mcontext; + unsigned long int uc_flags; +} ucontext_t; + +#endif /* !_SYS_UCONTEXT_H_ */ diff --git a/winsup/cygwin/include/ucontext.h b/winsup/cygwin/include/ucontext.h new file mode 100644 index 000000000..4240597b8 --- /dev/null +++ b/winsup/cygwin/include/ucontext.h @@ -0,0 +1,16 @@ +/* ucontext.h + + Copyright 2015 Red Hat, Inc. + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#ifndef _UCONTEXT_H +#define _UCONTEXT_H + +#include + +#endif /* _UCONTEXT_H */