Eric Blake wrote: > On the other hand, POSIX states for sigaction() that the handler's "third > argument can be cast to a pointer to an object of type ucontext_t to refer to > the receiving thread’s context that was interrupted when the signal was > delivered."
The type of the third argument, according to POSIX, is 'void *ucp'. Why does it have to be cast? Why is it not directly 'ucontext_t *ucp' (since, as you say, ucontext_t will be defined in <signal.h>)? > The receiving thread may currently be in the alternate stack, but > the signal was delivered when the thread was still in the primary stack. So > maybe we should file this as a bug with the kernel folks, and hope that a > future version of Linux change uc_stack to supply the information we want. > After all, we don't need uc_stack to learn about the current (alternate) > stack; > we can use sigaltstack() for that. I think you are misunderstanding things, and there is no Linux kernel bug here. When a signal S has been specified to execute on the alternate stack (via SA_ONSTACK), and SA_NODEFER is specified as well, when the signal S occurs a second time while the first signal occurrence is still being processed, the stack pointer cannot be set to the top of the alternating stack again - this room is already in use. So the second time the signal handling must behave as if there was no alternate stack. This is a semantic difference between the "context" of the main thread (where alternate signal stacks will be used when a signal occurs) and the "context" of signal handler (where alternate signal stacks will be ignored). This is why ucontext_t has a field 'uc_stack'. Whether sigaltstack(), when called during the signal handler, reports the existence of an alternate stack or not, is irrelevant. What matters, is the actual behaviour when a nested signal occurs. Some systems (OpenBSD, IRIX, Solaris) store the fact that the alternate stack is temporarily deactivated as a bit in the kernel. Others (Linux, MacOS X) determine it by looking whether the current stack pointer is in the range of the alternate stack. The description of 'uc_stack' in http://www.opengroup.org/susv3/basedefs/ucontext.h.html is so vague that I would not base any program on it. > > File platforms uses > > > > stackvma-linux.c Linux /proc/self/maps, mincore() > > stackvma-freebsd.c FreeBSD /proc/curproc/map, mincore() > > stackvma-mincore.c OpenBSD, NetBSD mincore() > > stackvma-mach.c MacOS X vm_region() > > stackvma-procfs.c IRIX, OSF/1, Solaris ioctl(PIOCMAP) > > stackvma-beos.c BeOS get_next_area_info() > > Cygwin provides /proc/self/maps (but not yet mincore()). Plus, you can > probably exploit the Windows API for both mingw and cygwin (perhaps in the > same > way that cygwin implements /proc/self/maps). You're right. Yes, in Cygwin and mingw, you can best use the Win32 VirtualQuery() API. > At any rate, the current implementation of c-stack precludes any > detection of non-stack overflow segv's on Linux (at least for the kernel > versions I was testing), because it claims ALL segvs are stack overflow, > whether or not that is true. Yes. Distinguishing between random SIGSEGV and stack overflow is a feature that IMO is unique to libsigsegv. > But m4's approach isn't quite right, either - on Linux, the current stack > location + getrlimit information when the overflow handler is registered > fails > to account for stack previously occupied prior to calling the handler Indeed. This area contains the command-line, the environment and - on HP-UX - also the shared libraries, and can therefore be quite large. Also, on IA64 processors, the hardware has two stack pointers which grow into opposite directions, from the start and the end of the assigned stack area. A stack overflow occurs when the two pointers cross - and at that time they are both far away from the point that you computed with getrlimit(). > Just so I'm clear: By stack top, you mean the area reserved by main(), and by > stack bottom, you mean the area near where the fault points on a stack > overflow? Yes. Nowadays the stack grows down on all CPUs except HPPA. > So c-stack could use a mincore()-like > capability to quickly determine whether all memory from the page near the > fault > over to the stack location saved at the time the handler was registered is > currently mapped (whether or not all of those pages are in core) (and > using /proc/self/maps when that is faster than mincore()). I agree with you that c-stack's use of 'uc_stack' is bogus, and on Linux, FreeBSD, OpenBSD, NetBSD, mincore() will give better results. Bruno