SafeStack proposal in GCC
Rich Felker
dalias@libc.org
Mon May 9 20:43:00 GMT 2016
On Mon, May 09, 2016 at 10:03:02PM +0200, Michael Matz wrote:
> Hi,
>
> On Mon, 9 May 2016, Rich Felker wrote:
>
> > > > The *context APIs are deprecated and I'm not sure they're worth
> > > > supporting with this. It would be a good excuse to get people to
> > > > stop using them.
> > >
> > > How? POSIX decided to remove the facilities without any adequate
> > > replacement (thread aren't).
> >
> > Threads work just as well as the ucontext api for coroutines. Due to the
> > requirement to save/restore signal masks, the latter requires a syscall,
> > making it no faster than a voluntary context switch via futex syscall.
>
> Uhm, no. If you disregard efficiency, sure, POSIX threads are sometimes a
> replacement on some platforms. They still have completely different
> activation models (being synchronous with *context, for which you need
> even further slow synchronization in a threading model).
switch_to_next:
sem_post(next->sem);
while (sem_wait(self->sem));
It can actually be done more idiomatically with cond vars, but I don't
see a way to make it as efficient.
> > Most of the other hacks people used the ucontext API for were complete
> > hacks with undefined behavior, anyway.
>
> Sure, that doesn't imply the facility should be removed. I can misuse all
> kinds of stuff.
Indeed.
> > BTW it's not even possible to implement makecontext on most targets due
> > to the wacky variadic calling convention it uses -- in most ABIs,
> > there's simply no way to shift the variadic args into the right slots
> > for calling the start function for the new context without knowing their
> > types, and the implementation has no way to know the types. So it's
> > really an unusably broken API.
>
> Of course. But _that_ implies that a workable replacement should have
> been put in place, not the unrealistic stance POSIX took with the removal:
> makecontext2(ucontext_t *ucp, void (*func)(void*), void* cookie);
It could have been done even more simply, without a new function, by
just saying the behavior is undefined unless func has type
void(*)(void), argc==1, and the first variadic arg has type void*.
> Done. I never understood why they left in the hugely
> unuseful {sig,}{set,long}jmp() but removed the actually useful *context()
> (amended somehow like above).
Because those are actually part of the C language (the non-sig
versions, but the sig versions are needed to work around broken unices
that made the non-sig versions save/restore signal mask and thus too
slow to ever use). They're also much more useful for actually
reasonable code (non-local exit across functions that were badly
designed with no error paths) as opposed to just nasty hacks that are
mostly/entirely UB anyway (coroutines, etc.).
Rich
More information about the Gcc
mailing list