Blake You will have to define what "portable C++" means. I don't really think that any of this actually has to do with C++. The method I outlined uses POSIX definitions (and, thus, is, by definition and standardization, "portable"). I even indicated where the method was outside of POSIX definition and scope.
What I don't know is the POSIX compliance of the operating environments that you want to be "portable" to/with. However, the technique I outlined is "compatible" with BSD Unix, Linux, Solaris, AIX and HP/UX across a variety of hardware platforms: Intel, Power, Itanium and (I believe) Z-series. What I *don't* know is if Microsoft Windows (in any of it's current incarnations) is included in the compatibility list (and, I suspect, there may be issues because, as far as I know, isn't GNU APL usually built with cygwin or something?). I personally *detest* #ifdef as a platform selection method. FredW On Sun, 2015-08-23 at 10:55 -0500, Blake McBride wrote: > If you do it, please do it in a (#ifdef) way so it can still be built > with > portable C++. > > Thanks! > > Blake > > > On Sun, Aug 23, 2015 at 9:08 AM, fred <[email protected]> > wrote: > > > Juergen > > > > Note that stack red-zones are typically already generated. So, you > > don't want to mess with that. The following plan will work in > > conjunction with the system stack red-zone. > > > > What I would do is: > > > > At startup, call down, with a defined limit. Each call level should > > take the local storage that is expected during "normal" calls. If > > this > > fails, the original target could not be achieved anyway. The > > signal() > > handler can be introduced before this is done. If a trap occurs, > > less > > stack nesting can be tried. On the deepest nesting, return a > > pointer to > > a local stack variable. Of course, this pointer cannot be used > > after > > return, but we just want to know the *location* of that memory. > > > > Use mprotect() on that pointer to establish the red page. a SIGSEGV > > will then be generated if the stack extends to that point. > > signal() > > will capture the SIGSEGV. Use setjmp() and longjmp() to unwind the > > stack after the SIGSEGV. > > > > Now, you want to use sigaction() to supply a sigaction handler, > > which > > gets passed a ucontext_t, which allows access to the actual address > > that caused the fault, the registers, etc. Old POSIX definition had > > it > > defined such that the fault could be processed, and a return from > > the signal handler would restart the instruction. More recent POSIX > > simply marked this as "undefined behaviour". > > > > This will work with both grow-up and grow-down stacks, *and* on > > implementations with "software stack". Eg. should work on Z-series. > > However, it is *not* (and cannot be) POSIX compliant. POSIX only > > allows > > mprotect() on mmap() memory (which is not stack memory). Also, > > POSIX > > specifies that execution becomes undefined after SIGSEGV -- even if > > it > > is caught. I just ignore these issues... (old POSIX, and very > > helpful > > if writing debug routines, and binary translators etc.). > > > > FredW > > > > > > > >
